python - 新的 PyYAML 版本在大多数自定义 python 对象上中断 - RepresenterError

标签 python yaml pyyaml

大约 5 小时前,版本 4.1.0 发布。它打破了我的单元测试。这是一个干净的 MVCE 显示:

版本 3.12:

>>> import numpy as np
>>> import yaml
>>> x = np.int64(2)
>>> yaml.dump(x, Dumper=yaml.Dumper)
'!!python/object/apply:numpy.core.multiarray.scalar\n- !!python/object/apply:numpy.dtype\n  args: [i8, 0, 1]\n  state: !!python/tuple [3, <, null, null, null, -1, -1, 0]\n- !!binary |\n  AgAAAAAAAAA=\n'

版本 4.1.0:

>>> import numpy as np
>>> import yaml
>>> x = np.int64(2)
>>> yaml.dump(x, Dumper=yaml.Dumper)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/foo/anaconda3/envs/bar/lib/python3.6/site-packages/yaml/__init__.py", line 217, in dump
    return dump_all([data], stream, Dumper=Dumper, **kwds)
  File "/foo/anaconda3/envs/bar/lib/python3.6/site-packages/yaml/__init__.py", line 196, in dump_all
    dumper.represent(data)
  File "/foo/anaconda3/envs/bar/lib/python3.6/site-packages/yaml/representer.py", line 26, in represent
    node = self.represent_data(data)
  File "/foo/anaconda3/envs/bar/lib/python3.6/site-packages/yaml/representer.py", line 57, in represent_data
    node = self.yaml_representers[None](self, data)
  File "/foo/anaconda3/envs/bar/lib/python3.6/site-packages/yaml/representer.py", line 229, in represent_undefined
    raise RepresenterError("cannot represent an object", data)
yaml.representer.RepresenterError: ('cannot represent an object', 2)

PyYAML 不再支持这些对象类型是否有明确的原因?

最佳答案

在 PyYAML 4.x 中,dumpsafe_dump 的别名,它不会处理任意对象:

>>> yaml.dump is yaml.safe_dump
True

对旧的 3.x 行为使用 danger_dump

>>> yaml.danger_dump(x)
'!!python/object/apply:numpy.core.multiarray.scalar\n- !!python/object/apply:numpy.dtype\n  args: [i8, 0, 1]\n  state: !!python/tuple [3, <, null, null, null, -1, -1, 0]\n- !!binary |\n  AgAAAAAAAAA=\n'

load/safe_load也是如此。找不到 4.1.0 的任何文档或发行说明,我只是通过挖掘提交 (here) 才发现的。

Is there a clear reason for why PyYAML no longer supports these object types?

是的。 yaml.load 允许任意代码执行,这样一个危险的功能应该只选择加入,不可能意外使用。按理说,从一开始就应该是这样的。


在当前的 PyYAML 5.x 中:您可以将加载器/转储器类指定为参数,而不是使用不同的函数:

yaml.dump(x, Dumper=yaml.Dumper)      # like "danger dump"
yaml.dump(x, Dumper=yaml.SafeDumper)  # like "safe_dump", won't dump python objs

与 3.x 一样,“危险”转储在 5.x 中仍然是默认值:

>>> yaml.dump(sys)
"!!python/module:sys ''\n"
>>> yaml.dump(sys, Dumper=yaml.SafeDumper)
RepresenterError: ('cannot represent an object', <module 'sys' (built-in)>)

关于python - 新的 PyYAML 版本在大多数自定义 python 对象上中断 - RepresenterError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51053903/

相关文章:

python - python中一个类的提款方法

python - Python 中的最优定向 Dijkstra 搜索

symfony - 按相关实体字段划分的学说顺序

python-3.x - PyYAML 转储没有标签的 Python 对象

python - 如何迭代 YAML 文件以给出 PYTHON 中不同列表中项目的所有可能组合

python - 从 subprocess.popen 获取总行数

python - 在 Windows 上的 python 中使用 libarchive

python - 如何使用python解析helm chart yaml文件

ruby - 无法挽救 YAML.load 异常

python - 如何打印出来!在皮亚姆尔?