【问题标题】:pyyam safe_dump doesn't work to get rid of tagspyyaml safe_dump 无法摆脱标签
【发布时间】:2022-01-04 15:25:44
【问题描述】:

根据对这个 SO question 的回答,我应该使用 safe_dump 而不是 dump 来删除不需要的标签,例如 !!python/unicode,但它对我不起作用。

在我个人的情况下,不需要的标签是!!python/object:module_example.items.ExampleItem,还添加了一个字典键_values。所有这一切可能是因为我使用的是scrapy,而我的item dict 是通过ExampleItem 类创建的。

代码如下:

import yaml

yaml.dump({'obj': item}, outfile)
# using safe_dump gives an empty output

当前输出:

obj: !!python/object:module_example.items.ExampleItem
  _values:
    first_name: 'foo'
    last_name: 'bar'

想要的输出:

obj:
  first_name: 'foo'
  last_name: 'bar'

如何去掉那些标签?

【问题讨论】:

  • 请出示您的代码。使用 Python3,您永远不会收到 !!python/unicode
  • @flyx 我将问题编辑得更准确

标签: python-3.x scrapy yaml tags pyyaml


【解决方案1】:

PyYAML 的一个重要方面是您通过您提供给 dump() 的值的类型来传达您的意图:如果您只提供 dictlist 和 str 值,您将获得没有标签的标准 YAML 输出。如果您提供其他内容,例如 ExampleItem 的类实例,您就是在告诉 PyYAML “我希望这个结构在我再次加载它时重新创建一个 ExampleItem 对象”。这就是 PyYAML 添加标签的原因。了解ExampleItem 的实例不是字典。

safe_dump() 限制您可以提供的类型:它只接受SafeDumper 已知的类型(您可以扩展)。因为你没有告诉它ExampleItem,所以它失败了。

如果您的目标是在输出中包含有关您的类型的任何信息,请不要提供非标准类型的值 - 仅提供 dictliststr .例如,你可以简单地做

yaml.dump({"obj": item.__dict__}, outfile)

但是,一旦item 包含更多非标准类型实例,此解决方案就不起作用。更通用的方法是注册自定义代表:

def clean_representer(dumper, data):
    return dumper.represent_mapping(
            yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, data.__dict__)

yaml.add_representer(ExampleItem, clean_representer)

print(yaml.dump({"obj": item}))

您可以对可能出现的每个类使用相同的clean_representer。通过将标签设置为 DEFAULT_MAPPING_TAG(即规范指定的 !!map),您允许 PyYAML 发射器省略标签。

或者,不要在对yaml.dump() 的调用中使用自定义类实例。这是否可能当然取决于您的代码;但是如果你只是建立一个数据结构来将它转储到 YAML,那么使用自定义类是没有意义的。

【讨论】:

  • 非常感谢。实际上这是一个类型问题,用dict(item) 替换item 解决了它。
猜你喜欢
  • 2021-03-27
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多