NewUser123
NewUser123

Reputation: 35

Using Python with YAML

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

Answers (3)

Anthon
Anthon

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

Orelus
Orelus

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

user5547025
user5547025

Reputation:

  • Open the file using "w", not "a".
  • You must also write a Person.
  • Use the option 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

Related Questions