Python 将具有拉丁-1字符的字节解码为具有十进制表示的字符串

Python 将具有拉丁-1字符的字节解码为具有十进制表示的字符串,python,python-3.x,python-3.6,iso-8859-1,Python,Python 3.x,Python 3.6,Iso 8859 1,我正在进行一个迁移项目,将web服务器层从Python2.7.8升级到Python3.6.3,我遇到了一些特殊情况下的障碍。 当从客户端接收到请求时,使用pyzmq在本地传输有效负载,pyzmq现在在python3中以字节进行交互,而不是以str进行交互(就像在python2中一样) 现在,我正在接收的有效负载是使用iso-8859-1(拉丁语-1)方案编码的,我可以轻松地将其转换为字符串作为有效负载。解码(“拉丁语-1”)并将其传递给下一个服务(svc save entity),该服务需要字符

我正在进行一个迁移项目,将web服务器层从Python2.7.8升级到Python3.6.3,我遇到了一些特殊情况下的障碍。 当从客户端接收到请求时,使用pyzmq在本地传输有效负载,pyzmq现在在python3中以
字节进行交互,而不是以
str
进行交互(就像在python2中一样)

现在,我正在接收的有效负载是使用iso-8859-1(拉丁语-1)方案编码的,我可以轻松地将其转换为字符串作为有效负载。解码(“拉丁语-1”)并将其传递给下一个服务(svc save entity),该服务需要字符串参数

但是,后续服务“svc save entity”希望拉丁字符-1(如果存在)以ASCII字符引用(例如
&233;
表示
)而不是十六进制(例如
\xe9
表示

我正在努力寻找一种有效的方式来实现这一转变。有python专家能在这里指导我吗?本质上,我需要一个函数的定义,比如说
decode\u-tostring()

请定义
解码字符串()
:)

方法
encode()
decode()
接受一个名为
errors
的参数,该参数允许您指定如何处理指定编码中不可表示的字符。您正在寻找的是XML数字字符引用替换,幸运的是,
编解码器
模块中提供了该替换

现在,实际按照您希望的方式进行替换有点复杂,因为用相应的XML数字字符引用替换非ASCII字符的操作发生在编码过程中,而不是解码过程中。毕竟,编码是一个接收字符并发出字节的过程,所以只有在编码过程中,您才能判断是否有一个字符不是ASCII的一部分。目前我能想到的获得所需转换的最干净的方法是解码、重新编码和重新解码,在编码步骤中应用XML实体引用替换

def decode_tostring(payload):
    return payload.decode('latin-1').encode('ascii', errors='xmlcharrefreplace').decode('ascii')
如果有一种方法可以用XML数字字符REF替换字符串中的所有非ASCII字符,并返回一个字符串,如果是这样,您可以使用它来替换编码和第二次解码,我也不会感到惊讶。但我不知道有一个。目前我发现的最接近的是,但这只作用于某些特定的角色


这与您的主要问题并不相关,但我确实想澄清一件事:XML是SGML、HTML和XML的一个特性,它们都是标记语言—一种将结构化数据表示为文本的方式。它们与ASCII无关。像ASCII这样的字符编码只不过是一个包含一些字符和一些字节序列的表,因此表中的每个字符都映射到表中的一个字节序列,反之亦然,并带有一些约束以使映射明确无误


如果字符串中的字符不在特定编码的表中,则不能使用该编码对该字符串进行编码。但您可以将该字符串转换为新字符串,方法是将表中不存在的字符替换为表中的字符序列,然后对新字符串进行编码。有许多方法可以进行替换,其中XML数字实体引用就是一个例子。Python的
编解码器
模块中的一些其他错误处理程序代表了这种替换的其他方法。

非常感谢@David Z提供您的输入,这些信息对我非常有用。我将继续寻找一种替代方法,它可以避免额外的编码和解码步骤。但同时,考虑到这些拉丁字母1字符在我的例子中很少出现,而且拉丁字母1代码从192开始,我可以在函数中检查-
(char>=192表示列表中的char(payload)):返回payload.decode('latin-1')。encode('ascii',errors='xmlcharrefreplace')。decode('ascii'))
else:return payload.decode('latin-1')
以上内容应该可以帮助我在大多数情况下避免额外的编码/解码。另外,对于第二次输入,在我的例子中,在保存实体之前,会发送一个通知,该通知根据配置可以是python dict格式或XML格式。当它以XML格式发送时是可以的,但当它以python dict格式发送时,如果遇到任何十六进制格式的拉丁字符(如
\xe9
),后续服务将无法处理它。也许在这方面需要改进,这可能是我的下一个任务:)
def decode_tostring(payload):
    return payload.decode('latin-1').encode('ascii', errors='xmlcharrefreplace').decode('ascii')