Vấn đề là bạn đang gọi encode
trên một str
đối tượng.
Một str
là một chuỗi byte, thường đại diện cho văn bản được mã hóa theo một cách nào đó như UTF-8. Khi bạn gọi encode
về điều đó, trước tiên nó phải được giải mã trở lại văn bản, vì vậy văn bản có thể được mã hóa lại. Theo mặc định, Python thực hiện điều đó bằng cách gọi s.decode(sys.getgetdefaultencoding())
và getdefaultencoding()
thường trả về 'ascii'
.
Vì vậy, bạn đang nói văn bản được mã hóa UTF-8, giải mã nó như thể nó là ASCII, sau đó mã hóa lại nó trong UTF-8.
Giải pháp chung là gọi decode
một cách rõ ràng với mã hóa phù hợp, thay vì để Python sử dụng mặc định, sau đó mã hóa encode
kết quả.
Nhưng khi mã hóa phù hợp đã là mã bạn muốn, giải pháp dễ dàng hơn là chỉ cần bỏ qua .decode('utf-8').encode('utf-8')
và chỉ sử dụng UTF-8 str
dưới dạng UTF-8 str
rằng nó đã là.
Hoặc, cách khác, nếu trình bao bọc MySQL của bạn có tính năng cho phép bạn chỉ định mã hóa và lấy lại unicode
giá trị cho CHAR
/ VARCHAR
/ TEXT
cột thay vì str
giá trị (ví dụ:trong MySQLdb, bạn chuyển use_unicode=True
với connect
gọi hoặc charset='UTF-8'
nếu cơ sở dữ liệu của bạn quá cũ để tự động phát hiện nó), chỉ cần làm điều đó. Sau đó, bạn sẽ có unicode
các đối tượng và bạn có thể gọi .encode('utf-8')
trên chúng.
Nói chung, cách tốt nhất để giải quyết các vấn đề Unicode là cách cuối cùng — giải mã mọi thứ càng sớm càng tốt, thực hiện tất cả các quá trình xử lý bằng Unicode và sau đó mã hóa càng muộn càng tốt. Nhưng dù bằng cách nào thì bạn cũng phải nhất quán. Không gọi str
trên một cái gì đó có thể là unicode
; không nối str
theo nghĩa đen của một unicode
hoặc chuyển một cái vào replace
của nó phương pháp; v.v ... Bất cứ khi nào bạn kết hợp và kết hợp, Python sẽ chuyển đổi ngầm cho bạn, sử dụng mã hóa mặc định của bạn, điều này hầu như không bao giờ là những gì bạn muốn.
Lưu ý thêm, đây là một trong nhiều điều mà các thay đổi Unicode của Python 3.x có ích. Đầu tiên, str
bây giờ là văn bản Unicode, không phải byte được mã hóa. Quan trọng hơn, nếu bạn có các byte được mã hóa, ví dụ:trong một bytes
đối tượng, gọi encode
sẽ cung cấp cho bạn một AttributeError
thay vì cố gắng giải mã một cách âm thầm để nó có thể mã hóa lại. Và, tương tự, cố gắng trộn và kết hợp Unicode và byte sẽ cho bạn một TypeError
rõ ràng , thay vì một chuyển đổi ngầm thành công trong một số trường hợp và đưa ra một thông điệp khó hiểu về một mã hóa hoặc giải mã mà bạn không yêu cầu ở những người khác.