user3170915
user3170915

Reputation: 117

Python how to read and write lists from files

I am pretty new to programming, I just recently finished the Python course in Codecademy, so I am sorry if this is a dumb question. I am working on a game so I can get more practice with what I already know. What I am trying to do is be able to read and write lists as well as mixed in variables in the .txt file. Here is what I have.

def read_file():
    global player_name, player_gender, player_lvl, player_gold, player_xp, player_items, strength, vitality, charisma, intellect, agility, player_hp, player_magicka, player_taunt, player_victory, player_fact, save_list, help_list
    save_file = open("savegame.txt", "r+")
    save_list = []
    for item in save_file:
        save_list.append(item)
    player_name = str(save_list[0])
    player_gender = str(save_list[1])
    player_lvl = int(save_list[2])
    player_gold = int(save_list[3])
    player_xp = int(save_list[4])
    player_items = [] #This is where I left it because I don't know how to read lists
    strength = int(save_list[6])
    vitality = int(save_list[7])
    intellect = int(save_list[8])
    charisma = int(save_list[9])
    agility = int(save_list[10])
    player_hp = int(save_list[11])
    player_magicka = int(save_list[12])
    player_taunt = str(save_list[13])
    player_victory = str(save_list[14])
    player_fact = player_name + str(save_list[15])

save_list is just the list I am extracting the variables and list from, I know it is probably not needed. On my fifth part of the list is where I want my other list to be, but I do not know how to get it out of its string form and turn it into a list. I know if this whole file was just one list I could iterate through it to make a list, but since I have other things around it, it's not that simple.

This is an example of what my save file(.txt) might look like. I need to figure out how to load the ["This part is supposed to be a list"] line as a list.

Mr May 
Male 
6
3340
1380
["This part is supposed to be a list"]
6
1
4
2
2
55
85
You suck!!!
I will never lose!!!
Mr May was tormented by potatoes as a child.

Also, it may be important to know my list will not stay the same size.

Any help is much appreciated, thank you.

Upvotes: 0

Views: 262

Answers (4)

Slick
Slick

Reputation: 359

The piece of info that we need to set here is how the data in the file is formatted. For example we could put an element on each line:

1
2
3

and I would call this "line delimited". What I would suggest is storing and loading the data in the JSON format.

import json
json.dump([1,2,3,4], open("outfile2.json", "w"))
save_list = json.load(open("outfile.json"))
save_list
[1, 2, 3, 4]

more documentation can be found here.

Upvotes: 2

Hugh Bothwell
Hugh Bothwell

Reputation: 56644

Something like

class Player:
    @classmethod
    def from_file(cls, fname):
        with open(fname) as inf:
            return cls(*(line.rstrip() for line in inf))

    def __init__(self, name, gender, health, hp, strength, charisma, intellect, agility, magicka, gold, xp, taunt, victory, items):
        self.name      = name
        self.gender    = gender
        self.health    = int(health)
        self.hp        = int(hp)
        self.strength  = int(strength)
        self.charisma  = int(charisma)
        self.intellect = int(intellect)
        self.agility   = int(agility)
        self.magicka   = int(magicka)
        self.gold      = int(gold)
        self.xp        = int(xp)
        self.taunt     = taunt
        self.victory   = victory
        self.items     = items.split(",")  # convert comma-delimited string to list

    def save_file(self, fname):
        with open(fname, "w") as outf:
            output = [
                self.name,
                self.gender,
                self.health,
                self.hp,
                self.strength,
                self.charisma,
                self.intellect,
                self.agility,
                self.magicka,
                self.gold,
                self.xp,
                self.taunt,
                self.victory,
                ",".join(self.items)    # convert list to comma-delimited string
            ]
            outf.write("\n".join(str(op) for op in output))

def main():
    char1 = Player.from_file("savegame.txt")
    # now do something with character!

if __name__=="__main__":
    main()

A list can be converted to a string using str.join, as in ",".join(mylist). This assumes that the elements of mylist are already strings. The string can then be converted back to a list of string using str.split(), as in mystr.split(",").

Using global variables is usually a bad idea because (a) it ties your function to a single set of variables - if you want to load a second character, you have to write another function; (b) it makes debugging harder because it is not obvious where data-changes are coming from; and (c) it clutters your global scope with lots of extraneous variables.

Making your function return a set of values or data structure is an improvement, in that it allows you to reuse code and reduces clutter; but it tends to lead to a whole bunch of functions that do various things to a data structure and often a bunch of similar-but-not-identical structures, with related almost-the-same functions and clutter and confusion.

The next step is make the various functions "belong to" their associated data structure - this is known as "object orientation" and is implemented in Python as a class. My code above creates a Player class which holds all related data for a single player and has member functions which can initialize a player, load one from file, or save back to file. I then have a main() function which demonstrates loading a player's data.

Several people have suggested using JSON as a storage type. This can be convenient, as it automatically converts strings and integers, lists and dictionaries; it is also easily edited by text editor or in other programs. On the other hand, it can be a bit of a trap, in that you end up dealing with a "bag of data" with associated clutter; it is unable to handle arbitrary data types ie classes.

Upvotes: -2

GoofyBall
GoofyBall

Reputation: 411

Although this does not answer your original question I think it would be better if you used JSON rather than a plain-text file. Using JSON, you won't have to deal with difficulties like parsing a list from a text file. To do this create a json file (mine is called "player.json") that has a structure something like this:

{ "player": "GoofyBall", "level": 2000, "items": [ "dagger", "sword", "wand of doom" ] }

You can then parse the file for the desired attributes. Here I have reduced the json file to just a few attributes for demonstration purposes but you can add to it as required:

import json

json_data=open('player.json') #open the json file
data = json.load(json_data) # load the json data

# get the attributes you want
print "Player name:" + data['player'] 
print "Level: " + str(data['level']) 
print "Items" + str(data['items']) 

I hope this helps your game.

Upvotes: 2

user3553966
user3553966

Reputation: 349

I do not understand quite what you mean. Should be clearer. But from what I saw you are going to work manipulating data of different types. It would be easier if you post the contents of the file: savegame.txt.

For example. If this file has the following line in 5 Content: Item 1, Item 2, Item 3. You can get a new list using the split.

As follows: player_items = save_list.[5].split (",")

The split works with a key character. In the example above I have used ','

This will return you to a new list: ["Item 1", "Item 2", "Item 3"]

Upvotes: 1

Related Questions