python - 为什么 PyYAML/ruamel 在 Python 2 上结合转义代理?
问题描述
对于在 YAML 文件中指定其某些测试用例的 Python 项目,我想在 YAML 测试用例中以 UTF-8 编码指定字节字符串,包括无效的 UTF-8 序列,例如未配对的代理或交换高/低代理目的是测试 Python 项目对它们的处理。
我在测试用例 YAML 中使用双引号标量(因为这是在 YAML 中指定转义序列的唯一方法)和 16 位 unicode 转义(例如“\u03B5”)来指定代理代码点。
我们的 Python 项目使用 PyYAML 加载测试用例 YAML 文件,但我验证以下结果也适用于 ruamel。以下是 PyYAML 的示例(在 Python 2.7 和 3.7 上,除非另有说明,在 macOS 上使用 CPython):
>>> import yaml # PyYAML
# some valid Unicode character (lower case greek epsilon, fwiw)
>>> yaml.safe_load('x: "\\u03B5"')
{'x': u'\u03b5'}
# invalid unpaired surrogate
>>> yaml.safe_load('x: "\\uD800"')
{'x': u'\ud800'}
# invalid swapped high/low surrogates
>>> yaml.safe_load('x: "\\uDC00\\uD800"')
{'x': u'\udc00\ud800'}
# valid surrogates, but using surrogates is illegal in UTF-8
>>> yaml.safe_load('x: "\\uD800\\uDC00"')
{'x': '\ud800\udc00'} # on Python 3.7
{'x': u'\U00010000'} # on Python 2.7 <-- why??
上面最后一个案例在 Python 2.7 上的行为使得无法按预期将该案例传递给我们的 Python 项目,因为它被 PyYAML 或 Python 本身“纠正”了。
这种“更正”发生在哪里,可以禁用吗?
解决方案
我不确定您使用的是什么版本,但我无法重现。只有libyaml
您的输入似乎有问题:
from __future__ import print_function
import sys
print('Python: ', sys.version_info[:2])
import yaml as pyyaml
print('PyYAML: ', pyyaml.__version__)
import ruamel.yaml
print('ruamel.yaml:', ruamel.yaml.version_info)
yaml_str = 'x: "\\uD800\\uDC00"'
print('yaml_str', yaml_str)
print(repr(pyyaml.safe_load(yaml_str)['x']))
for typ, pure in [('rt', True), ('safe', True), ('safe', False)]:
yaml = ruamel.yaml.YAML(typ=typ, pure=pure)
data = yaml.load(yaml_str)
print(repr(data['x']))
给出:
Python: (2, 7)
PyYAML: 5.1.2
ruamel.yaml: (0, 16, 6, u'dev')
yaml_str x: "\uD800\uDC00"
u'\ud800\udc00'
u'\ud800\udc00'
u'\ud800\udc00'
Traceback (most recent call last):
File "/tmp/ryd-of-anthon/ryd-111/tmp_0.py", line 20, in <module>
data = yaml.load(yaml_str)
File "/home/anthon/.venv/27/lib/python2.7/site-packages/ruamel/yaml/main.py", line 341, in load
return constructor.get_single_data()
File "/home/anthon/.venv/27/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 111, in get_single_data
node = self.composer.get_single_node()
File "_ruamel_yaml.pyx", line 706, in _ruamel_yaml.CParser.get_single_node
File "_ruamel_yaml.pyx", line 724, in _ruamel_yaml.CParser._compose_document
File "_ruamel_yaml.pyx", line 775, in _ruamel_yaml.CParser._compose_node
File "_ruamel_yaml.pyx", line 889, in _ruamel_yaml.CParser._compose_mapping_node
File "_ruamel_yaml.pyx", line 731, in _ruamel_yaml.CParser._compose_node
File "_ruamel_yaml.pyx", line 904, in _ruamel_yaml.CParser._parse_next_event
ruamel.yaml.scanner.ScannerError: while parsing a quoted scalar
in "<byte string>", line 1, column 4
found invalid Unicode character escape code
in "<byte string>", line 1, column 7
推荐阅读
- android - Android 10 MediaStore API 更改
- c++ - 如何获取在 CStaticCtrl 上播放的 libVLC 媒体的点击事件
- javascript - 从 facebook-passport 回调重定向后缺少 cookie
- javascript - 在模态中获取输入类型=日期的值
- csv - Spark:如何定义模式以读取具有不同列数的 csv 文件?
- java - 通过参数泛型方法查找 JPA 存储库
- android - 应用程序作为“后台进程”打开。有可能反应原生吗?
- qt - 用于浏览某些层次结构的导航栏
- css - 是否可以使用 CSS nth-child 来遵循这种模式?
- php - 为什么“电子邮件发送失败:SMTP 连接()失败。” 启用不太安全的应用程序后仍然出现