避免在PyYAML中引用

Ger*_*nuk 8 python yaml

我使用YAML和PyYAML.在转储嵌套结构后,有没有办法避免*id002引用?为了便于阅读,我想在那里看到实际的(元组)值.

在尝试生成一个迷你示例时,我注意到它只在我使用相同的id对象时才会发生:

import yaml

t = ("b", "c")
x = {(1, t):1, (2, t):2, }
print(yaml.dump(x))
Run Code Online (Sandbox Code Playgroud)

所以我认为copy.copy()可以解决问题,但是对于元组它似乎不起作用:(我可以创建一个具有不同ID的新元组吗?

Ant*_*hon 13

PyYAML转储程序使用一种ignore_aliases方法来防止基本类型以这种方式"锚定"和"引用".您可以将该方法重写为始终ignore_aliases,而不依赖于传入的任何对象.默认情况下,yaml.Loader该类用于yaml.load¹:

t = ("b", "c")
x = {(1, t):1, (2, t):2, }

yaml.Dumper.ignore_aliases = lambda *args : True

yaml.dump(x, sys.stdout)
Run Code Online (Sandbox Code Playgroud)

会得到你:

? !!python/tuple
- 1
- !!python/tuple [b, c]
: 1
? !!python/tuple
- 2
- !!python/tuple [b, c]
: 2
Run Code Online (Sandbox Code Playgroud)

这样你就不必尽力而为,并使用相同的哈希来获得看起来不同的元组.你可能想提供default_flow_style参数上yaml.loadFalseTrue得到输出的不同布局.

您无法使其工作的原因是,表示符匹配结果,id()并且只要元素相同,两个元组分别生成的结果相同.


¹ 我只尝试使用ruamel.yaml,其中我是作者,它是PyYAML的增强版本,但为此,两者应该相同.

  • 另外,如果您使用 yaml.safe_dump() 来删除 ? 来自 yaml 的!!python/tuple`。您将需要覆盖“yaml.SafeDumper.ignore_aliases”。该示例将变为:“yaml.SafeDumper.ignore_aliases = lambda *args : True”和“yaml.safe_dump(x, sys.stdout)” (2认同)

dpj*_*nes 7

这个方法适用于Python 2和Python 3,并且不需要monkeypatching:

import yaml

class NoAliasDumper(yaml.SafeDumper):
    def ignore_aliases(self, data):
        return True

t = ("b", "c")
x = {(1, t):1, (2, t):2, }
print(yaml.dump(x, Dumper=NoAliasDumper))
Run Code Online (Sandbox Code Playgroud)

这产生

? - 1
  - [b, c]
: 1
? - 2
  - [b, c]
: 2
Run Code Online (Sandbox Code Playgroud)