Reputation: 35
I have a YAML file where I want to store different "players" in my game.
the YAML file looks like this:
Person:
Name:
Age:
Nationality:
Footed:
Position:
After I have created a player the YAML file should look like this:
Person:
Name: Rich
Age: 23
Nationality: British
Footed: Right
Position: Forward
So far my code is like this:
import yaml
name = input('What is your name? ')
age = int(input('What is your age? '))
nationality = input('What is your nationality? ')
footed = input('What foot? ')
position = input('What is your position? ')
with open('test.yml', 'a') as outfile:
outfile.write(yaml.dump({'Name' : name, 'Age' : age, 'Nationality' : nationality,
'Footed' : footed, 'Position' : position}))
but when I run this and give the user input the yaml file ends up looking like:
{Age: 2, Footed: r, Name: r, Nationality: r, Position: r}
How do I get it to add to the YAML file rather than append and also how do I structure it vertically rather than horizontally? Finally, if I want to add 10/20/n number of players I would like the YAML file to store them all one under each other so that I can call each one individually
Upvotes: 1
Views: 2167
Reputation: 76832
When you write out your YAML as you do, you first write the data structure to a file in memory, then retrieve the memory-file content as a string, and then write it to a file. That is inefficient and slow.
You also should just read in the YAML file you have, update the datastructure and dump it:
import yaml
file_name = 'test.yml'
with open(file_name) as infile:
data = yaml.load(infile)
person = data['Person']
person['name'] = input('What is your name? ')
person['age'] = int(input('What is your age? '))
person['nationality'] = input('What is your nationality? ')
person['footed'] = input('What foot? ')
person['position'] = input('What is your position? ')
with open(file_name, 'w') as outfile:
yaml.dump(data, stream=outfile, default_flow_style=False, indent=3)
The default_flow_style
parameter makes sure your key-value pairs are listed below each other.
With PyYAML any comments in the infile will be lost and the order of the keys in the mapping probably will be scrambled. If that is a problem I recommend that you use ruamel.yaml package (disclaimer: I am the author of that package), and change the code to:
import ruamel.yaml
file_name = 'test.yml'
with open(file_name) as infile:
data = ruamel.yaml.round_trip_load(infile)
person = data['Person']
person['name'] = input('What is your name? ')
person['age'] = int(input('What is your age? '))
person['nationality'] = input('What is your nationality? ')
person['footed'] = input('What foot? ')
person['position'] = input('What is your position? ')
with open(file_name, 'w') as outfile:
yaml.round_trip_dump(data, stream=outfile, indent=3)
If you want to store multiple players. Make sure your toplevel datastructure is a sequence, or is mapping from some unique value (e.g. the name of the Person). In that case use a different input file as template and update the output file by reading it in, appending to the list cq. updateing the dict and writing out the file. As long as the names are unique it is easier to do this with a toplevel mapping/dict.
Upvotes: 1
Reputation: 1023
You can do like this:
import pyaml as yaml
name = input('What is your name? ')
age = int(input('What is your age? '))
nationality = input('What is your nationality? ')
footed = input('What foot? ')
position = input('What is your position? ')
person = {'Person':{
'Name': name,
'Age': age,
'Nationality': nationality,
'Footed': footed,
'Position': position}
}
with open('test.yml', 'a') as outfile:
yaml.dump(person, outfile, indent=4)
Upvotes: 0
Reputation:
"w"
, not "a"
.Person
.default_flow_style=False
.Code:
with open('test.yml', 'w') as outfile:
outfile.write(yaml.dump(
{"Person": {
'Name' : name,
'Age' : age,
'Nationality' : nationality,
'Footed' : footed,
'Position' : position}
},
default_flow_style=False))
Output
Person:
Name: Rich
Age: 23
Nationality: British
Footed: Right
Position: Forward
Upvotes: 0