我知道在SO上有一些关于这个的问题,但我找不到我想要的东西。
我正在使用pyyaml读取(.load()
).yml
文件,修改或添加密钥,然后再次编写它(.dump()
)。问题是我想在转储后保留文件格式,但它会改变。
例如,我编辑关键en.test.index.few
说"Bye"
而不是"Hello"
蟒蛇:
with open(path, 'r', encoding = "utf-8") as yaml_file:
self.dict = pyyaml.load(yaml_file)
然后,更改密钥后:
with open(path, 'w', encoding = "utf-8") as yaml_file:
dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None)
yaml_file.write( dump )
YAML:
之前:
en:
test:
new: "Bye"
index:
few: "Hello"
anothertest: "Something"
后:
en:
anothertest: Something
test:
index:
few: Hello
new: Bye
有没有办法保持相同的格式?,例如报价和订单。我使用了错误的工具吗?
我知道也许原始文件不完全正确,但我无法控制它(这是一个Ruby on Rails i18n文件)。
非常感谢你。
请改用ruamel.yaml
。
PyYAML是effectively dead,已经有好几年了。更复杂的是,http://pyyaml.org的官方项目似乎最近被取消了。该网站托管了PyYAML问题跟踪器,文档和下载。在撰写本文时,一切都已消失。这简直就是灾难性的。欢迎来到开源的另一天。
ruamel.yaml
是actively maintained。与PyYAML不同,ruamel.yaml
支持:
yaml.dump()
来转储先前调用yaml.load()
所加载的字典时:
PyYAML天真地忽略了所有输入格式 - 包括注释,排序,引用和空格。像这么多的数字垃圾一样丢弃到最近的可用位桶。
ruamel.yaml
巧妙地尊重所有输入格式。一切。整个风格的辣酱玉米饼馅。整个文学shebang。所有。由于ruamel.yaml
是一个PyYAML分支,因此符合PyYAML API,因此在现有应用程序中从PyYAML切换到ruamel.yaml
通常就像替换所有实例一样简单:
# This imports PyYAML. Stop doing this.
import yaml
...有了这个:
# This imports "ruamel.yaml". Always do this.
from ruamel import yaml
而已。
不需要进行其他更改。 yaml.load()
和yaml.dump()
函数应该继续按预期运行 - 现在支持YAML 1.2并积极接收错误修复的额外好处。
为了向后兼容PyYaml,yaml.load()
和yaml.dump()
函数默认不执行往返保存。为此,请明确传递:
Loader=ruamel.yaml.RoundTripLoader
的可选yaml.load()
关键字参数。Dumper=ruamel.yaml.RoundTripDumper
的可选yaml.dump()
关键字参数。一个从ruamel.yaml
documentation“借来”的例子:
import ruamel.yaml
inp = """\
# example
name:
# Yet another Great Duke of Hell. He's not so bad, really.
family: TheMighty
given: Ashtaroth
"""
code = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader)
code['name']['given'] = 'Astarte' # Oh no you didn't.
print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='')
它完成了。现在将完整保留注释,排序,引用和空白。
始终使用ruamel.yaml
。永远不要使用PyYAML。 ruamel.yaml
生活。 PyYAML是一个腐烂的尸体,在PyPi的砾石地面腐烂。
ruamel.yaml
万岁。
第一
使用以下代码表示字典数据:
mapping = list(mapping.items())
try:
mapping = sorted(mapping)
except TypeError:
pass
这就是订购改变的原因
第二
有关标量类型如何呈现(带双引号或不带引号)的信息在读取时丢失(这是库的主要方法)
摘要
您可以基于'Dumper'创建自己的类,并重载方法'represent_mapping'以更改字典将如何呈现的行为
为了保存关于标量的双引号的信息,你还必须根据'Loader'创建自己的类,但我担心它会影响和其他类,并且会很难
在我的情况下,如果值包含"
或{
,我想要}
,否则没有。例如:
en:
key1: value is 1
key2: 'value is {1}'
要执行该操作,请从模块PyYaml中的文件representer.py复制函数represent_str()
,如果字符串包含{
或}
,则使用另一种样式:
def represent_str(self, data):
tag = None
style = None
# Add these two lines:
if '{' in data or '}' in data:
style = '"'
try:
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
except UnicodeDecodeError:
try:
data = unicode(data, 'utf-8')
tag = u'tag:yaml.org,2002:str'
except UnicodeDecodeError:
data = data.encode('base64')
tag = u'tag:yaml.org,2002:binary'
style = '|'
return self.represent_scalar(tag, data, style=style)
要在您的代码中使用它:
import yaml
def represent_str(self, data):
...
yaml.add_representer(str, represent_str)
在这种情况下,键和值之间没有差异,这对我来说已经足够了。如果你想要一个不同的键和值样式,用函数qazxsw poi执行相同的操作