python - _Exact_ सममूल्य `बी '...'.decode(" utf-8 "," backslashreplace ")` पायथन 2 में




python-2.7 python-3.x (2)

आप अपना स्वयं का त्रुटि हैंडलर लिख सकते हैं यहाँ एक समाधान है जिसे मैंने पायथन 2.7, 3.3 और 3.6 पर परीक्षण किया है:

from __future__ import print_function
import codecs
import sys

print(sys.version)

def myreplace(ex):
    # The error handler receives the UnicodeDecodeError, which contains arguments of the
    # string and start/end indexes of the bad portion.
    bstr,start,end = ex.object,ex.start,ex.end

    # The return value is a tuple of Unicode string and the index to continue conversion.
    # Note: iterating byte strings returns int on 3.x but str on 2.x
    return u''.join('\\x{:02x}'.format(c if isinstance(c,int) else ord(c))
                    for c in bstr[start:end]),end

codecs.register_error('myreplace',myreplace)
print(b'\xc2\xa1\xa1ABC'.decode("utf-8", "myreplace"))

आउटपुट:

C:\>py -2.7 test.py
2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)]
¡\xa1ABC

C:\>py -3.3 test.py
3.3.5 (v3.3.5:62cf4e77f785, Mar  9 2014, 10:35:05) [MSC v.1600 64 bit (AMD64)]
¡\xa1ABC

C:\>py -3.6 test.py
3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
¡\xa1ABC

पायथन 3.5+। .decode("utf-8", "backslashreplace") में आंशिक-यूनिकोड, अंशतः-कुछ अज्ञात-विरासत-एन्कोडिंग बाइनरी स्ट्रिंग्स से निपटने के लिए एक बहुत अच्छा विकल्प है। मान्य यूटीएफ -8 दृश्यों को डीकोड किया जाएगा और अमान्य लोगों को एस्केप अनुक्रम के रूप में संरक्षित किया जाएगा। उदाहरण के लिए

>>> print(b'\xc2\xa1\xa1'.decode("utf-8", "backslashreplace"))
¡\xa1

यह b'\xc2\xa1\xa1' और b'\xc2\xa1\xa1' b'\xc2\xa1\\xa1' b'\xc2\xa1\xa1' बीच का अंतर खो देता है, लेकिन अगर आप "मुझे कुछ भी हानिपूर्ण नहीं b'\xc2\xa1\\xa1' हैं कि मैं बाद में हाथ से ठीक कर सकता हूँ" मन की सीमा, यह शायद ठीक है

हालांकि, यह पायथन 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

मुझे एक सन्निकटन मिल गया है, लेकिन सटीक समकक्ष नहीं है:

>>> print(b'\xc2\xa1\xa1'.decode("latin1")
...       .encode("ascii", "backslashreplace").decode("ascii"))
\xc2\xa1\xa1

यह बहुत महत्वपूर्ण है कि व्यवहार दुभाषिया संस्करण पर निर्भर नहीं है। क्या कोई 2.7 और 3.4 में बिल्कुल पायथन 3.5 व्यवहार प्राप्त करने का तरीका सुझा सकता है?

(या तो 2.x या 3.x के पुराने संस्करणों को काम करने की आवश्यकता नहीं है। बंदर पट्टी codecs पूरी तरह स्वीकार्य है।)


मैंने cpython कार्यान्वयन के अधिक पूर्ण बैकपोर्ट का प्रयास किया

यह दोनों UnicodeDecodeError ( .decode() ) के साथ ही .encode() और .translate() से .translate() को .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'))




backwards-compatibility