Nguồn chính của các vấn đề mà tôi đã gặp phải khi làm việc với các chuỗi unicode là khi bạn trộn các chuỗi được mã hóa utf-8 với các chuỗi unicode.
Ví dụ, hãy xem xét các tập lệnh sau.
two.py
# encoding: utf-8
name = 'helló wörld from two'
one.py
# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name
Đầu ra của việc chạy python one.py
là:
Traceback (most recent call last):
File "one.py", line 5, in <module>
print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
Trong ví dụ này, two.name
là một chuỗi được mã hóa utf-8 (không phải unicode) vì nó không nhập unicode_literals
và one.name
là một chuỗi unicode. Khi bạn kết hợp cả hai, python sẽ cố gắng giải mã chuỗi được mã hóa (giả sử đó là ascii) và chuyển đổi nó thành unicode và không thành công. Nó sẽ hoạt động nếu bạn đã làm print name + two.name.decode('utf-8')
.
Điều tương tự cũng có thể xảy ra nếu bạn mã hóa một chuỗi và cố gắng trộn chúng sau đó. Ví dụ, điều này hoạt động:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Đầu ra:
DEBUG: <html><body>helló wörld</body></html>
Nhưng sau khi thêm import unicode_literals
nó KHÔNG:
# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Đầu ra:
Traceback (most recent call last):
File "test.py", line 6, in <module>
print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)
Nó không thành công vì 'DEBUG: %s'
là một chuỗi unicode và do đó python cố gắng giải mã html
. Một số cách để sửa bản in đang thực hiện print str('DEBUG: %s') % html
hoặc print 'DEBUG: %s' % html.decode('utf-8')
.
Tôi hy vọng điều này sẽ giúp bạn hiểu được các lỗi tiềm ẩn khi sử dụng chuỗi unicode.
decode()
giải pháp thay vìstr()
hoặcencode()
các giải pháp: bạn càng sử dụng các đối tượng Unicode thường xuyên hơn, mã càng rõ ràng, vì những gì bạn muốn là thao tác các chuỗi ký tự, không phải mảng byte với mã hóa ngụ ý bên ngoài.