Ask coding questions

← Back to all posts
Import objects from user input? (Python)
MuffinsTheCat (18)

I am working on a game where the player can have multiple save games at once, and the player has to input the name of the savefile they want. How do I then convert their input into importing their chosen savefile?

Comments
hotnewtop
RYANTADIPARTHI (6001)

Solution

try an if statement.

user = input('save or no?')

if user == 's':
    # imports, and code for saving
else:
    # code for else part.

something like that.
it should work

MuffinsTheCat (18)

@RYANTADIPARTHI Yes this would work but the game works as the save file having the same name as the player

19wintersp (1121)

What language is this in? (And note that files made by programs on Replit will not persist)

19wintersp (1121)

@MuffinsTheCat What you would do is take the user's input specifying the file, open the file, parse its contents, and use that as the data. Here's a small example:

mode = input("[L]oad or [s]ave? ").lower()
file_name = input("File name? ")

if mode == "l":
  #this opens the file, and closes it automatically
  with open(file_name, "r") as file:
    print("Here's your save data:")
    print(file.read()) #read the file with read(), and print it
elif mode == "s":
  with open(file_name, "w") as file:
    data_to_save = input("What data do you want to save? ")
    file.write(data_to_save) #write the data to the file with write()
    print("Saved!")
else:
  print("Not an option")

However, as I said initially, be wary that changes made to files by programs on Replit will not persist.

MuffinsTheCat (18)

@19wintersp While this would work, the game gets saved as a .py file then imported later so the usual f = open will not work for this. Do you have any way to make something like

from (savename) import *

work? I tried this but it tries to import the name of the object rather than the object itself

19wintersp (1121)

@MuffinsTheCat That's not how imports generally work, and you probably shouldn't do things in this way. Could you explain what is being saved into that file? There is likely a better solution - though there is a way (hack) of doing this.

MuffinsTheCat (18)

@19wintersp Basically this is how one thing gets saved:

health = 20
health = str(health)
saveline1 = ("health = " + health + "\n") #exclude the \n for the last line
f = open(playername, "w")
f.write(saveline1)
#repeat for the remaining savelines
f.close
19wintersp (1121)

@MuffinsTheCat Since you're not executing any script there, why do you need to save it as a Python file? You could use a custom key/value system:

#saving
saveline1 = "health=" + str(health) + "\n"
f = open(playername, "w")
f.write(saveline1)
f.close()

#loading
f = open(playername, "r")
savelines = f.read().split("\n")
f.close()
for line in savelines:
  [key, value] = line.split("=")
  if key == "health":
    health = int(value)

(a better version would stop keys and values from having "=" in them, and maybe use a dictionary) or you could use a built-in serialisation library like for JSON:

import json

#saving
f = open(playername, "w")
f.write(json.dumps({"health": health}))
f.close()

#loading
f = open(playername, "r")
savedata = json.loads(f.read())
f.close()
health = savedata["health"]
MuffinsTheCat (18)

@19wintersp Thank you for your help. I understand that I would repeat

f.write(json.dumps({"health": health}))

for every value but replacing health, but how do I do this with classes and lists?

19wintersp (1121)

@MuffinsTheCat The other issue with using a Python file to do this is that the file is executed, meaning of someone tried to load a maliciously-crafted save file, unintended arbitrary code execution could take place. For example, if it was made so that "health" was "1;print('hacked')", the savefile would be this:

health = 1;print('hacked')

When imported, this save file will print "hacked".

19wintersp (1121)

@MuffinsTheCat If you want to preserve the classes, you may want to look into Pickle, but that has loads of other issues. To save a list, just put it into the dictionary as you would for a regular Python dictionary. You can generate a dictionary from an object with the __dict__ property, and assign to __dict__ too.