ruamel.yaml 不解释单个字符串,它解释
流它被处理,即.load()的参数。如果说
参数是字节流或类似对象的文件,则其编码为
根据 BOM 确定,默认为 UTF-8。但又一次:那是
在流级别,而不是在单个标量内容之后
解释逃逸。既然你手 .load() Unicode (因为这是
Python 3)“流”不需要进一步解码。 (虽然
与这个问题无关:它是在reader.py:Reader 方法stream 和
determine_encoding)
十六进制转义(\xAB 形式)只会放置一个特定的十六进制
加载器用来构造标量的类型中的值,即
键“b”的值,这是一个普通的 Python 3 str,即 Unicode 在
其内部表示之一。你得到â 在你的
输出是因为您的 Python 配置为如何对其进行解码str
类型。
所以你不会“找到”ruamel.yaml 解码的地方
字节序列,因为它已经被假定为 Unicode。
所以要做的是你双重解码你的双引号
标量(您只需将它们作为简单的单引号,
文字/折叠标量不能有十六进制转义)。有各种
您可以尝试这样做的点,但我认为
constructor.py:RoundTripConsturtor.construct_scalar 和
scalarstring.py:DoubleQuotedScalarString 是最佳人选。前者可能需要一些挖掘才能找到,但后者实际上是你检查时会得到的类型
添加选项以保留引号时加载后的该字符串:
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load('a:\n b: "\\xE2\\x80\\x99"\n')
print(type(data['a']['b']))
哪个打印:
<class 'ruamel.yaml.scalarstring.DoubleQuotedScalarString'>
知道你可以检查那个相当简单的包装类:
class DoubleQuotedScalarString(ScalarString):
__slots__ = ()
style = '"'
def __new__(cls, value, anchor=None):
# type: (Text, Any) -> Any
return ScalarString.__new__(cls, value, anchor=anchor)
“更新”那里唯一的方法 (__new__) 做你的双重
编码(您可能必须进行额外的检查才能不对所有编码进行双重编码
双引号标量0:
import sys
import codecs
import ruamel.yaml
def my_new(cls, value, anchor=None):
# type information only needed if using mypy
# value is of type 'str', decode to bytes "without conversion", then encode
value = value.encode('latin_1').decode('utf-8')
return ruamel.yaml.scalarstring.ScalarString.__new__(cls, value, anchor=anchor)
ruamel.yaml.scalarstring.DoubleQuotedScalarString.__new__ = my_new
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load('a:\n b: "\\xE2\\x80\\x99"\n')
print(data)
给出:
ordereddict([('a', ordereddict([('b', '’')]))])