python - Yaml Python 2.7 和 Python 3.7 兼容转储和加载 unicode 字符
问题描述
我在使用 PyYaml 加载/转储 yaml 文件时遇到问题,这些文件需要与 Python 2 和 Python 3 兼容。
对于 Python 3 转储/Python 2 加载,我找到了一个解决方案:
import yaml
data = {"d": ""}
with open(file_path, "w") as f:
yaml.dump(data, f, allow_unicode=True)
这会生成一个带有以下行的 yaml 文件:
d:
如果我尝试使用 Python 2 加载此文件:
with open(file_path, "r") as f:
y = yaml.safe_load(f)
print(y["d"])
我得到以下输出:
但是现在如果我尝试使用 Python 2 转储文件,我尝试了:
data = {"d": u""}
with open(file_name, "w") as f:
yaml.dump(f)
这会产生一个 yaml 文件:
d: "\uD83D\uDE0B"
我也试过:
data = {"d": u"".encode("utf-8")}
with open(file_name, "w") as f:
yaml.dump(f)
这会产生一个 yaml 文件:
d: !!python/str "\uD83D\uDE0B"
在这两种情况下,如果我使用 Python 3 加载:
with open(file_path, "r") as f:
y = yaml.load(f)
then y["d"]
is'\ud83d\ude0b'
不能按原样使用。
我发现我可以做类似的事情
y["d"].encode("utf-16", "surrogatepass").decode("utf-16")
但这似乎有点矫枉过正。
那么使用 Python 2 转储一个在 Python 3 中可读且正确解释的文件的解决方案是什么?
解决方案
我最终为此添加了一个构造函数。我将它添加到自定义加载器中,所以我这样做self.add_constructor
了,但在 yaml 级别上是相同的,更容易说明。
yaml.add_constructor("tag:yaml.org,2002:python/str", unicode_constructor)
def unicode_constructor(loader, node):
scalar = loader.construct_scalar(node)
return scalar.encode("utf-16", "surrogatepass").decode("utf-16")
这适用于 Python2 转储/Python 3 加载
并且不影响 Python 3 转储/Python 2 或 3 加载
推荐阅读
- swiftui - 如何使用 SwiftUI2 网格创建“砌体式”布局?
- python - 为什么我的输出在创建 dict() 时返回“None None”?
- javascript - 尝试清除/清空/删除/设置回初始状态时,React setState 挂钩不起作用
- linux - Linux下调试.NET Core
- pandas - 如何在 pandas groubpy 对象上调用不同的聚合操作
- ios - IOS操作完成后如何释放vImage缓冲区
- reactjs - Electron React App,路径未映射到构建文件夹中的 JS 文件
- node.js - cy.task() with require('oracledb') 抛出错误
- javascript - 如何从包含多个数组的 JSON 中提取所有数据?
- c# - 返回一个元组而不是抛出异常是一个坏主意吗?