Đây là một vấn đề phổ biến, vì vậy đây là một minh họa tương đối kỹ lưỡng.
Đối với các chuỗi không phải unicode (tức là những chuỗi không có u
tiền tố như u'\xc4pple'
), người ta phải giải mã từ mã hóa gốc ( iso8859-1
/ latin1
, trừ khi được sửa đổi bằngsys.setdefaultencoding
hàm bí ẩn ) unicode
, sau đó mã hóa thành một bộ ký tự có thể hiển thị các ký tự bạn muốn, trong trường hợp này tôi muốn giới thiệu UTF-8
.
Đầu tiên, đây là một chức năng tiện ích hữu ích sẽ giúp làm sáng tỏ các mẫu của chuỗi Python 2.7 và unicode:
>>> def tell_me_about(s): return (type(s), s)
Một chuỗi đơn giản
>>> v = "\xC4pple"
>>> tell_me_about(v)
(<type 'str'>, '\xc4pple')
>>> v
'\xc4pple'
>>> print v
?pple
Giải mã chuỗi iso8859-1 - chuyển đổi chuỗi thuần thành unicode
>>> uv = v.decode("iso-8859-1")
>>> uv
u'\xc4pple'
>>> tell_me_about(uv)
(<type 'unicode'>, u'\xc4pple')
>>> print v.decode("iso-8859-1")
Äpple
>>> v.decode('iso-8859-1') == u'\xc4pple'
True
Minh họa thêm một chút - với “Ä”
>>> u"Ä" == u"\xc4"
True
>>> "Ä" == u"\xc4"
False
>>> "Ä".decode('utf8') == u"\xc4"
True
>>> "Ä" == "\xc4"
False
Mã hóa thành UTF
>>> u8 = v.decode("iso-8859-1").encode("utf-8")
>>> u8
'\xc3\x84pple'
>>> tell_me_about(u8)
(<type 'str'>, '\xc3\x84pple')
>>> u16 = v.decode('iso-8859-1').encode('utf-16')
>>> tell_me_about(u16)
(<type 'str'>, '\xff\xfe\xc4\x00p\x00p\x00l\x00e\x00')
>>> tell_me_about(u8.decode('utf8'))
(<type 'unicode'>, u'\xc4pple')
>>> tell_me_about(u16.decode('utf16'))
(<type 'unicode'>, u'\xc4pple')
Mối quan hệ giữa unicode và UTF và latin1
>>> print u8
Äpple
>>> print u8.decode('utf-8')
Äpple
>>> print u16
���pple
>>> print u16.decode('utf16')
Äpple
>>> v == u8
False
>>> v.decode('iso8859-1') == u8
False
>>> u8.decode('utf-8') == v.decode('latin1') == u16.decode('utf-16')
True
Ngoại lệ Unicode
>>> u8.encode('iso8859-1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)
>>> u16.encode('iso8859-1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0:
ordinal not in range(128)
>>> v.encode('iso8859-1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0:
ordinal not in range(128)
Ai có thể làm được việc này bằng cách chuyển đổi từ mã hóa cụ thể (latin-1, utf8, UTF16) để unicode ví dụ u8.decode('utf8').encode('latin1')
.
Vì vậy, có lẽ người ta có thể rút ra các nguyên tắc và khái quát sau:
- một loại
str
là một tập hợp các byte, có thể có một trong số các mã hóa như Latin-1, UTF-8 và UTF-16
- một loại
unicode
là một tập hợp các byte có thể được chuyển đổi thành bất kỳ số lượng mã hóa nào, phổ biến nhất là UTF-8 và latin-1 (iso8859-1)
- các
print
lệnh có logic riêng của nó để mã hóa , thiết lập để sys.stdout.encoding
và mặc định là UTF-8
- Người ta phải giải mã a
str
thành unicode trước khi chuyển đổi sang một bảng mã khác.
Tất nhiên, tất cả những thay đổi này trong Python 3.x.
Hy vọng rằng điều đó đang sáng.
đọc thêm
Và những câu nói rất minh họa của Armin Ronacher: