python - 将具有 latin-1 字符的字节解码为具有十进制表示的字符串
问题描述
我正在做一个迁移项目,将一层 web 服务器从 python 2.7.8 升级到 python 3.6.3,我遇到了一些特殊情况的障碍。当从客户端接收到请求时,有效负载使用 pyzmq 在本地传输,它现在bytes
在 python3 中交互,而不是str
(就像在 python2 中一样)。
现在,我收到的有效负载使用iso-8859-1 (latin-1)方案进行编码,我可以轻松地将其转换为字符串作为payload.decode('latin-1')并将其传递给下一个服务(svc- save-entity),它需要字符串参数。
但是,后续服务 ' svc-save-entity ' 期望 latin-1 字符(如果存在)以 ASCII 字符参考(例如é
for é
)而不是十六进制(例如\xe9
for é
)表示。
我正在努力寻找一种有效的方法来实现这种转换。任何python专家都可以在这里指导我吗?本质上我需要一个函数的定义说decode_tostring()
:
payload = b'Banco Santander (M\xe9xico)' #payload is in bytes
payload_str = decode_tostring(payload) #function to convert into string
payload_str == 'Banco Santander (México)' #payload_str is a string in ASCII Character Reference
请的定义decode_tostring()
。:)
解决方案
encode()
anddecode()
方法接受一个名为的参数,该参数errors
允许您指定如何处理在指定编码中不可表示的字符。您正在寻找的是 XML 数字字符引用替换,幸运的是,它是模块中提供的标准处理程序之一。codecs
现在,以您想要的方式实际进行替换有点复杂,因为将非 ASCII 字符替换为其对应的 XML 数字字符引用的操作发生在编码期间,而不是解码期间。毕竟,编码是一个接收字符并发出字节的过程,所以只有在编码过程中,你才能知道你是否有一个不属于 ASCII 的字符。目前我能想到的获得所需转换的最简洁方法是解码、重新编码和重新解码,在编码步骤中应用 XML 实体引用替换。
def decode_tostring(payload):
return payload.decode('latin-1').encode('ascii', errors='xmlcharrefreplace').decode('ascii')
如果有一种方法可以将字符串中的所有非 ASCII 字符替换为它们的 XML 数字字符引用并返回一个字符串,我不会感到惊讶,如果是这样,您可以使用它来替换编码和第二次解码。但我不知道一个。我目前发现的最接近的是xml.sax.saxutils.escape()
,但这仅对某些特定字符起作用。
这与您的主要问题并不真正相关,但我确实想澄清一件事:数字实体é
是 SGML、HTML 和 XML 的一个特性,它们是标记语言 - 一种将结构化数据表示为文本的方法。它们与 ASCII 无关。像 ASCII 这样的字符编码只不过是一些字符和一些字节序列的表,这样表中的每个字符都映射到表中的一个字节序列,反之亦然,有一些约束可以使映射明确。
如果您的字符串包含不在特定编码表中的字符,则无法使用该编码对字符串进行编码。但是您可以做的是将字符串转换为新字符串,方法是将表中没有的字符替换为表中的字符序列,然后对新字符串进行编码。有很多方法可以进行替换,其中 XML 数字实体引用就是一个例子。Pythoncodecs
模块中的一些其他错误处理程序代表了这种替换的其他方法。
推荐阅读
- php - 需要代码从 WordPress 中的帖子中删除链接
- tfs - 将工作项从一个集合的团队项目单独移动到另一个集合
- c - 如果我想在 C 中写入数组,如何使数组发挥作用?
- javascript - componentDidMount() 在 render() 方法之前渲染
- javascript - amphtml 标记显示错误“引用的 AMP URL 不是 AMP”
- graph - 给定一个表示 n 个元素之间成本的邻接矩阵,我如何将 n 个元素分成 k 个组?
- jsonschema - 'if, then and else' 关键字可以应用在对象的属性中还是严格保留在外部?
- angular - 了解功能模块中的 Angular 路由
- ios - 使用 AudioKit 导出过滤后的音频
- swift - 如何检测spritekit中的双击