0

I'm writing a game in Python that uses a save file feature. I've written a function that saves all the necessary variables, strings, lists and dictionaries to a file. All in all, there are 11 things to import when I call a function called "load()" which I wrote.

Here is load():

def load():
    importedData = open("saveGame.dat", "r+").readlines()
    for x in range(0,len(importedData)):
    position = importedData[0]
    health = importedData[1]
    strength = importedData[2]
    exp = importedData[3]
    playerLevel = importedData[4]

    # playerSpells = []
    # spellsFromSaveFile = importedData[5]
    # This doesn't work!

    playerClass = importedData[6]
    seenDialogues = importedData[7]
    rank = importedData[8]
    playerItems = importedData[9]
    itemDesc = importedData[10]
    specialItems = importedData[11]
return position, health, strength, exp, playerLevel, playerSpells, playerClass, seenDialogues, rank, playerItems, itemDesc, specialItems

And here is what the save file looks like:

2
24
4
96
1
['Blink']
None
2
Frajan
[]
{}
{}

Most of the dictionaries and lists will be blank, as they are used for items that are picked up later in the game (this save file was created early on in the game).

While I need to import a couple of lists and dictionaries, I'll focus on one of them. The list playerSpells is saved as ['Blink'] in the save file, "saveGame.dat".

Here's what I've tried:

I've imported the list into a list called playerSpells:

playerSpells = []
playerSpells = importedData[5]
print(playerSpells)

The line print(playerSpells) returns this:

['Blink']

This seems like it worked, so I added the following loop:

playerSpells = []
playerSpells = importedData[5]
for x in range(0,len(playerSpells)):
    print(playerSpells[x])

But got this:

[
'
B
l
i
n
k
'
]

So, my question is: How would I go about importing a list, from a file, into another list - but adding words to the list, not single characters?

Any help appreciated.

String
  • 155
  • 1
  • 5
  • 12
  • You would be better off using e.g. [`pickle`](https://docs.python.org/2/library/pickle.html) to persist actual objects, rather than writing them all out as text representations. The only downside is that the file isn't human-readable. – jonrsharpe May 30 '15 at 11:36
  • @jonrsharpe I read about `pickle`, and thought about using it, but at the moment I'm bugfixing the savefiles and they need to be readable so I can tweak things! If I get them sorted, I may use `pickle`. – String May 30 '15 at 11:37
  • 1
    You could also use JSON. Works like pickle and human-readable. And readable in every other language of course. – Martin Preusse May 30 '15 at 11:40
  • Fair enough. It looks like you could really do with a class to store all of these related variables, which you can also use `pickle` to store and recreate. – jonrsharpe May 30 '15 at 11:40

2 Answers2

2

['Blink'] is read as a string. You can evaluate the string to get a Python list:

import ast

playerSpells_list = ast.literal_eval(playerSpells)

There is also the built in eval(). See this question for an explanation why ast is better.

Community
  • 1
  • 1
Martin Preusse
  • 9,151
  • 12
  • 48
  • 80
2

With playerSpells = importedData[5] you stored a string in the playerSpells variable, instead of a list. Since Python is not strongly typed, it does not complain. However, when you iterate over the string, you get a character in each iteration, which is then printed.

The dirty fix to this is to use

import ast
playerSpells = ast.literal_eval(importedData[5])

However there are better solutions. What you are doing here is called deserialization, i.e. transforming a string back to the data structure it was originally serialized from. There are a lot of ways to do this nicely in Python.

I recommend you check out the pickle module, which was constructed specifically for this task in Python or use JSON (short for JavaScript Object Notation), which is a generally accepted way to store data structures and will work well with most languages. Python has a module to deal with it as well.

Cu3PO42
  • 1,403
  • 1
  • 11
  • 19