2009-10-06 46 views
5

tôi nhận được mã hóa lỗi trên dòng này:Tại sao tôi gặp lỗi mã hóa trong cảnh báo python.formatwarning trên chuỗi định dạng?

s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message) 

UnicodeEncodeError: 'ascii' codec có thể không mã hóa kí tự u '\ xc4' ở vị trí 44: thứ tự không trong phạm vi (128)

tôi đã cố gắng để tạo lại lỗi này bằng cách chuyển tất cả các kết hợp của tham số sang định dạng chuỗi, nhưng gần nhất tôi nhận được lỗi "ascii decode" (bằng cách chuyển chuỗi unciode và ascii cao đồng thời, buộc chuyển đổi chuỗi thành unicode, sử dụng bộ giải mã ascii.

Tuy nhiên, tôi không quản lý để có được "ascii mã hóa" lỗi.Bất cứ ai có một ý tưởng?

+1

Ồ, 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. –

Trả lời

8

này xảy ra khi Python cố gắng ép buộc một cuộc tranh cãi:

s = u"\u00fc" 
print str(s) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 0: ordinal not in range(128) 

Điều này xảy ra bởi vì một trong những lý lẽ của bạn là một đối tượng (không phải là một chuỗi dưới mọi hình thức) và Python gọi str() trên đó. Có hai giải pháp: Sử dụng chuỗi unicode cho định dạng (s = u"%s...") hoặc quấn từng đối số bằng repr().

+1

Định dạng nằm trong mô-đun cảnh báo, vì vậy tôi không muốn thay đổi nó, nhưng thêm repr() xung quanh các thông số được truyền âm thanh thực sự tốt. Cảm ơn bạn! –

+0

Sau đó, bạn sẽ nhận được thêm dấu ngoặc kép và thêm một u. Làm việc như một hack, nhưng không phải là rất đẹp. –

+1

Lỗi xảy ra khi cảnh báo được ném bởi cơ sở dữ liệu được ghi lại để ghi nhật ký. Khi đăng nhập thất bại, tôi hoàn toàn chìm trong bóng tối về vấn đề ban đầu, đó là nơi tồi tệ nhất. Tôi thích các bản ghi của mình có thể đọc được như là người tiếp theo, vì vậy tôi đã quyết định quấn định dạng trong một lần thử: ngoại trừ: chặn, làm đầu tiên "độc đáo" và chỉ sử dụng repr() trong trường hợp lỗi mã hóa, bao gồm cả cảnh báo phụ về vấn đề mã hóa. IMHO, Đó không phải là một hack, nó tốt hơn, an toàn hơn, đăng nhập. –

1

Một trong các toán hạng bạn đang chuyển không phù hợp với mã hóa ASCII - có lẽ nó chứa ký tự Unicode hoặc Latin-1. Thay đổi chuỗi định dạng thành Unicode và xem điều gì xảy ra.

+0

Điều này sẽ tạo ra một lỗi _decode_, tức là s = "% s% s"% (unichr (2000), chr (200)) Lỗi ở đây có vẻ là một cái gì đó khác. –

+0

@cortex: Đôi khi Python quyết định không ép buộc để unicode, nhưng coerce để chuỗi. Tôi không chắc chính xác quyết định đó được đưa ra như thế nào. –

8

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.

+2

Tôi nghĩ rằng người hỏi là hoàn toàn nhận thức được thực tế là vấn đề là unicode và str được trộn lẫn bằng cách nào đó; câu hỏi là tại sao lỗi này được kích hoạt trên một hoạt động mà thông thường nên ép buộc đầu ra thành unicode. –

+1

Có thể, nhưng tôi đã đi cho một câu trả lời đầy đủ. Và vấn đề vẫn là sự pha trộn của unicode và str. Tại sao nó lại bị lỗi thay vì cái kia trong trường hợp cụ thể mà tôi không biết, tôi không thể tái tạo nó. Nhưng tôi đã thấy nó xảy ra bản thân mình. –

+1

Đó là cách bạn có thể tái tạo nó: 'cảnh báo nhập khẩu; warnings.warn (u'Предупреждение ') ' –

Các vấn đề liên quan