Python 如何解码字节(使用ASCII)而不丢失任何;“垃圾”;如果xmlcharrefresplace和反斜杠替换don';不行?

Python 如何解码字节(使用ASCII)而不丢失任何;“垃圾”;如果xmlcharrefresplace和反斜杠替换don';不行?,python,python-3.x,encoding,byte,Python,Python 3.x,Encoding,Byte,我有一个网络资源,它返回的数据(根据规范)应该是ASCII编码的字符串。但在少数情况下,我会得到垃圾数据 例如,一个资源返回b'\xd3PS-90AC',而另一个资源返回b'PS-90AC' 第一个值包含非ASCII字符串。显然违反了规范,但不幸的是这超出了我的控制范围。我们中没有人100%确定这真的是垃圾或应该保留的数据 调用远程资源的应用程序将数据保存在本地数据库中以供日常使用。我可以简单地做一个数据解码('ascii','replace')或..'ignore'),但这样我就会丢失数据,而

我有一个网络资源,它返回的数据(根据规范)应该是ASCII编码的字符串。但在少数情况下,我会得到垃圾数据

例如,一个资源返回
b'\xd3PS-90AC'
,而另一个资源返回
b'PS-90AC'

第一个值包含非ASCII字符串。显然违反了规范,但不幸的是这超出了我的控制范围。我们中没有人100%确定这真的是垃圾或应该保留的数据

调用远程资源的应用程序将数据保存在本地数据库中以供日常使用。我可以简单地做一个
数据解码('ascii','replace')
..'ignore')
,但这样我就会丢失数据,而这些数据以后可能会很有用

我的直接反应是使用
'xmlcharrefreplace'
'backslaschreplace'
作为错误处理程序。只是因为它会产生一个可显示的字符串。但是我得到了以下错误:
TypeError:不知道如何处理错误回调中的UnicodeDecodeError

唯一有效的错误处理程序是
subscrateescape
,但这似乎是针对文件名的。另一方面,就我的意图和目的而言,它会起作用

为什么
'xmlcharrefreplace'
'backslashreplace'
不起作用?我不明白这个错误

例如,预期的执行将是:

>>> data = b'\xd3PS-90AC'
>>> new_data = data.decode('ascii', 'xmlcharrefreplace')
>>> print(repr(new_data))
'&#d3;PS-90AC'
这是一个人为的例子。我的目标是不丢失任何数据。如果我使用
ignore
replace
错误处理程序,所涉及的字节将基本上消失,信息也将丢失

>>> data = b'\xd3PS-90AC'
>>> data.decode('ascii', 'surrogateescape')
'\udcd3PS-90AC'
它不使用html实体,但这是一个不错的起点。如果不够,您将不得不使用我的假设注册您自己的错误处理程序

对于Python3:

def handler(err):
    start = err.start
    end = err.end
    return ("".join(["&#{0};".format(err.object[i]) for i in range(start,end)]),end)

import codecs
codecs.register_error('xmlcharreffallback', handler)
data = b'\xd3PS-90AC'
data.decode('ascii', 'xmlcharreffallback')
对于Python 2

def handler(err):
    start = err.start
    end = err.end
    return (u"".join([u"&#{0};".format(ord(err.object[i])) for i in range(start,end)]),end)

import codecs
codecs.register_error('xmlcharreffallback', handler)
data = b'\xd3PS-90AC'
data.decode('ascii', 'xmlcharreffallback')
两者都产生:

'ÓPS-90AC'

为了完整起见,我想补充一下,从Python3.5开始,
backslashreplace
用于解码,因此您不再需要添加自定义错误处理程序。

我不清楚预期的“输出”是什么。您想将“ASCII”字符串和“垃圾”字节放在一起(比如
u'\u00d3PS-90AC'
)?或者类似于
data.decode('unicode_escape')
的结果?我添加了一些示例执行。并不是说示例输出有点来自我的头顶。如果它使用不同的语法,那没关系。我添加了标记Python3,因为您的示例暗示了这一点。还是我错了?这很好;)as
SubrogateScape
backslashreplace
仅存在于Python3中。目前,我正在编写的库仍被一个Python2应用程序使用,因此首选Python2解决方案,但我们计划最终将剩下的一个应用程序移植到Python3。所以没关系。。。最糟糕的情况是,我们现在就得把它移植过来:)我一直在读这个话题。我不确定我最初使用
xmlcharrefreplace
的想法是否是个好主意。引用的值指向“Unicode代码点”。通过查找
211
,我找到了
ȑ
(utf-8字节值
C891
)。因此,我不确定您将如何从
211
返回到
\xd3
。我认为使用
subrogateScape
可能不会那么模棱两可\也许我们过于关注“如何”而不真正知道你想做什么。是时候问另一个问题了:)?@exhuma BTW
211
(10)是
d3
(16)。这只不过是一个简单的dec->hex转换。话虽如此,我个人会推动使用Unicode代码点。但是一旦angin没有澄清你对“瘾君子字符串”的用法,就很难说了。你是对的。我想过去两天我看字节太多了。我可能应该休息一下。