Bạn đang trộn các đối tượng unicode và str.
Giải thích: Trong Python 2.x, có hai loại đối tượng có thể chứa chuỗi văn bản. str, và unicode. str là một chuỗi các byte, vì vậy nó chỉ có thể chứa các ký tự từ 0 đến 255. Unicode là một chuỗi các ký tự unicode.
Bạn có thể chuyển đổi giữa str và unicode với "mã hóa" và "giải mã" các phương pháp:
>>> "thisisastring".decode('ascii')
u'thisisastring'
>>> u"This is ä string".encode('utf8')
'This is \xc3\xa4 string'
Lưu ý các bảng mã. Mã hóa là cách biểu diễn văn bản unicode như chỉ các chuỗi byte.
Nếu bạn cố gắng thêm str và unicode cùng nhau, Python sẽ cố gắng chuyển đổi một cái khác. Nhưng theo mặc định, nó sẽ sử dụng ASCII làm mã hóa, có nghĩa là a-z, A-Z và một số ký tự phụ như !"#$%&/()=?'{[]]}
vv Mọi thứ khác sẽ thất bại.
Bạn sẽ vào thời điểm đó hoặc nhận được lỗi mã hóa hoặc lỗi giải mã, tùy thuộc vào nếu Python cố gắng chuyển đổi unicode thành str hoặc str thành unicode. Thông thường nó cố gắng giải mã, đó là chuyển đổi sang unicode. Nhưng đôi khi nó quyết định không nhưng để ép buộc vào chuỗi. Tôi không hoàn toàn chắc chắn tại sao.
Cập nhật: Lý do bạn nhận được lỗi mã hóa chứ không phải lỗi giải mã ở trên là message
trong mã ở trên không phải là đường cũng không phải là unicode. Đó là một đối tượng khác, có phương thức str. Do đó Python thực hiện str (message) trước khi truyền nó vào, và thất bại, vì thông điệp lưu trữ nội bộ là một đối tượng unicode không thể bị ép buộc thành ascii.
Hoặc, đơn giản hơn đã trả lời: Không thành công vì warnings.warn() không chấp nhận thông báo unicode.
Bây giờ, các giải pháp:
Không trộn lẫn str và unicode. Nếu bạn cần phải sử dụng unicode, và bạn dường như làm, cố gắng để đảm bảo tất cả các chuỗi được unicode tất cả các thời gian. Đó là cách duy nhất để chắc chắn bạn tránh điều này. Điều này có nghĩa rằng bất cứ khi nào bạn đọc trong một chuỗi từ đĩa, hoặc một cuộc gọi đến một hàm có thể trả về bất cứ điều gì khác hơn là đường ascii tinh khiết, giải mã nó thành unicode càng sớm càng tốt. Và khi bạn cần lưu nó vào đĩa hoặc gửi nó qua mạng hoặc chuyển nó vào một phương thức không hiểu unicode, hãy mã hóa nó thành str càng sớm càng tốt.
Trong trường hợp cụ thể này, sự cố là bạn chuyển mã unicode thành warnings.warn() và bạn không thể thực hiện điều đó. Vượt qua một chuỗi. Nếu bạn không biết nó là gì (như trường hợp ở đây) vì nó đến từ một nơi khác, các giải pháp try/except của bạn với một repr hoạt động tốt, mặc dù thực hiện một mã hóa sẽ là một khả năng.
Ồ, bạn nhận được nó khi warnings.warn được gọi là ... Bạn không thể nói như vậy? Không rõ mã không phải là mã của bạn nhưng trong thư viện chuẩn. Bạn nên nói vấn đề của bạn là gì, không phải là một câu hỏi chung mà bạn nghĩ là vấn đề, bởi vì nó thường không phải là vấn đề. Tôi đã cập nhật câu trả lời của mình bên dưới với nhiều chi tiết hơn. –