这是我的代码:

import yaml
yaml.load('foo')

此代码导致PyYAML(5.1)出现以下警告.

$ pip install pyyaml
$ python3 foo.py
foo.py:2: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
  yaml.load('foo')

因此,我访问了https://msg.pyyaml.org/load,看看这是怎么回事,但我不明白这个警告的必要性.

首先,文件上说,

UnsafeLoader(也称为Loader,表示向后兼容)

原始加载程序代码,不受信任的数据输入很容易利用这些代码.

好吧,这是有道理的.在早期版本中,原始加载程序不安全.它还说,

FullLoader

加载完整的YAML语言.避免任意代码执行.这是yaml.load(input)(发出警告后)调用的默认加载程序(PyYAML 5.1).

因此,目前的版本使用FullLoader,这不是不安全的.文件中再次确认了这一点.

通过禁止默认加载程序(FullLoader)执行任意函数,加载函数也变得更加安全.

如果目前使用FullLoader的版本不是不安全的,那么为什么我们需要YAMLLoadWarning呢?

推荐答案

我认为这更像是一个警告;指导,让用户知道PyYAMLfuture 的最佳实践是什么.回想一下:Explicit is better than implicit.


在版本5.1(例如4.1)之前,yaml.load api默认使用Loader=Loader:

def load(stream, Loader=Loader):
    """
    Parse the first YAML document in a stream
    and produce the corresponding Python object.
    """
    loader = Loader(stream)
    try:
        return loader.get_single_data()
    finally:
        loader.dispose()

def safe_load(stream):
    """
    Parse the first YAML document in a stream
    and produce the corresponding Python object.
    Resolve only basic YAML tags.
    """
    return load(stream, SafeLoader)

当时,Loader class人只有三种 Select :有限的BaseLoader人、SafeLoader人和不安全的Loader人.虽然默认的是不安全的,就像我们从文档中读到的:

PyYAML的load函数自5月份首次发布以来一直不安全

但是仍然有很多资源和教程倾向于直接使用yaml.load(f),因此用户(尤其是新用户) Select 默认的加载程序类implicitly.


自PyYAML版本5.1以来,yaml.load api更改为explicit:

def load(stream, Loader=None):
    """
    Parse the first YAML document in a stream
    and produce the corresponding Python object.
    """
    if Loader is None:
        load_warning('load')
        Loader = FullLoader

    loader = Loader(stream)
    try:
        return loader.get_single_data()
    finally:
        loader.dispose()

def safe_load(stream):
    """
    Parse the first YAML document in a stream
    and produce the corresponding Python object.
    Resolve only basic YAML tags. This is known
    to be safe for untrusted input.
    """
    return load(stream, SafeLoader)

Loader classes中增加了一个新的FullLoader.作为用户,我们也应该意识到这些变化,并多使用yaml.load explicitly:

  • yaml.load(stream, yaml.SafeLoader)

    建议用于不受信任的输入.限制:加载YAML语言的一个子集.

  • yaml.load(stream, yaml.FullLoader)

    获取更可信的输入.还有一点限制:避免执行任意代码.

  • yaml.load(stream, yaml.Loader)(UnsafeLoaderLoader相同)

    不安全的但它拥有全部的力量.

Python-3.x相关问答推荐

背包问题-如何减少内存使用

使用Python请求从特定URL下载图像时出错

Pyvis和Networkx:如何根据源或目标使 node colored颜色 不同

将数据帧扩展为矩阵索引

tkinter treeview 如何在获取所选项目时将设置的对象作为对象返回

链接列未延伸到数据框的末尾

如何通过 python 使用 auth no priv 获取 SNMPv3?

如何在 on_ready 事件中使用 change_presence? (discord.py)

在 Django 中执行 JSONRenderer.render(serialized_student_data.data) 时遇到问题

运行 pip install -r requirements.txt 时出错

解包时是否可以指定默认值?

为 python3 安装 opencv

Python 3x 的最佳机器学习包?

python 3.4版不支持'ur'前缀

迭代dict值

IronPython 3 支持?

用于 unicode 大写单词的 Python 正则表达式

命名参数可以与 Python 枚举一起使用吗?

连接 dict 值,它们是列表

将 Python 字节转换为无符号 8 位整数