【问题标题】:Using Python with YAML将 Python 与 YAML 结合使用
【发布时间】:2016-09-05 04:26:12
【问题描述】:

我有一个 YAML 文件,我想在我的游戏中存储不同的“玩家”。

YAML 文件如下所示:

Person:
  Name:
  Age:
  Nationality:
  Footed:
  Position:

创建播放器后,YAML 文件应如下所示:

Person:
   Name: Rich
   Age: 23 
   Nationality: British
   Footed: Right
   Position: Forward

到目前为止,我的代码是这样的:

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}))

但是当我运行它并给用户输入时,yaml 文件最终看起来像:

{Age: 2, Footed: r, Name: r, Nationality: r, Position: r}

如何让它添加到 YAML 文件而不是追加,以及如何垂直而不是水平地构造它?最后,如果我想添加 10/20/n 个播放器,我希望 YAML 文件将它们全部存储在彼此之下,以便我可以单独调用每个播放器

【问题讨论】:

  • 仅(大部分)PyYAML 支持 2005 年以来的 YAML 1.1 标准。自 2009 年以来,最新的 YAML 版本是 1.2

标签: python file yaml pyyaml


【解决方案1】:

当您像这样写出 YAML 时,首先将数据结构写入内存中的文件,然后将内存文件内容作为字符串检索,然后将其写入文件。那是低效且缓慢的。

您还应该只读取您拥有的 YAML 文件,更新数据结构并将其转储:

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)

default_flow_style 参数确保您的键值对列在彼此下方。

使用 PyYAML,infile 中的任何 cmets 都将丢失,并且映射中键的顺序可能会被打乱。如果这是一个问题,我建议您使用 ruamel.yaml 包(免责声明:我是该包的作者),并将代码更改为:

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)

如果您想存储多个播放器。确保您的顶级数据结构是一个序列,或者是从某个唯一值(例如人的名称)映射的。在这种情况下,使用不同的输入文件作为模板并通过读入来更新输出文件,并将其附加到列表 cq。更新字典并写出文件。只要名称是唯一的,使用顶级映射/字典就更容易做到这一点。

【讨论】:

  • 我还没有使用ruamel.yaml,但是我在上面的实现中遇到了这个错误`文件“yaml_example.py”,第8行,在 person = data['Person'] TypeError : 'NoneType' 对象不可下标`
  • 对我来说,它提示 What is your name? 提供 PyYAML 和 ruamel.yaml 版本。检查您的test.yml,它可能是空的。
  • 好的,它现在正在粘贴到 yaml 文件中,但它会这样粘贴:test.yml ... 这当然是不正确的
  • 转储的第一个参数当然必须是data 而不是file_name
  • 如果混乱成为问题,请将 PyYAML 替换为 ruamel.yaml,这样就不会发生。
【解决方案2】:

你可以这样做:

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)

【讨论】:

    【解决方案3】:
    • 使用"w"而不是"a"打开文件。
    • 您还必须写一个Person
    • 使用选项default_flow_style=False

    代码:

    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))
    

    输出

    Person:
       Name: Rich
       Age: 23 
       Nationality: British
       Footed: Right
       Position: Forward
    

    【讨论】:

      猜你喜欢
      • 2019-04-01
      • 2018-02-19
      • 1970-01-01
      • 2020-03-11
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      相关资源
      最近更新 更多