zwo*_*wol 14 python encoding backwards-compatibility python-2.7 python-3.x
在Python 3.5+ .decode("utf-8", "backslashreplace")中,处理部分Unicode,部分未知的遗留编码二进制字符串是一个非常好的选择.将解码有效的UTF-8序列,并将无效的序列保留为转义序列.例如
>>> print(b'\xc2\xa1\xa1'.decode("utf-8", "backslashreplace"))
¡\xa1
Run Code Online (Sandbox Code Playgroud)
这就失去了b'\xc2\xa1\xa1'和之间的区别b'\xc2\xa1\\xa1',但是如果你在"只是给我一些不太有损的东西,以后我可以手工修理"的心态,那可能就行了.
但是,这是Python 3.5中的一项新功能.我正在研究的程序也需要支持3.4和2.7.在这些版本中,它会抛出异常:
>>> print(b'\xc2\xa1\xa1'.decode("utf-8", "backslashreplace"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
TypeError: don't know how to handle UnicodeDecodeError in error callback
Run Code Online (Sandbox Code Playgroud)
我找到了一个近似值,但不是一个确切的等价物:
>>> print(b'\xc2\xa1\xa1'.decode("latin1")
... .encode("ascii", "backslashreplace").decode("ascii"))
\xc2\xa1\xa1
Run Code Online (Sandbox Code Playgroud)
行为不依赖于解释器版本是非常重要的.任何人都可以建议的方式来获得精确地在2.7和3.4的Python 3.5的行为?
(2.x或3.x的旧版本不需要工作.猴子修补codecs是完全可以接受的.)
这既处理UnicodeDecodeError(from .decode())又处理UnicodeEncodeErrorfrom .encode()和UnicodeTranslateErrorfrom .translate():
from __future__ import unicode_literals
import codecs
def _bytes_repr(c):
"""py2: bytes, py3: int"""
if not isinstance(c, int):
c = ord(c)
return '\\x{:x}'.format(c)
def _text_repr(c):
d = ord(c)
if d >= 0x10000:
return '\\U{:08x}'.format(d)
else:
return '\\u{:04x}'.format(d)
def backslashescape_backport(ex):
s, start, end = ex.object, ex.start, ex.end
c_repr = _bytes_repr if isinstance(ex, UnicodeDecodeError) else _text_repr
return ''.join(c_repr(c) for c in s[start:end]), end
codecs.register_error('backslashescape_backport', backslashescape_backport)
print(b'\xc2\xa1\xa1after'.decode('utf-8', 'backslashescape_backport'))
print(u'\u2603'.encode('latin1', 'backslashescape_backport'))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1594 次 |
| 最近记录: |