2017-01-10 18 views
6

tôi nhận được một lỗi trong một hệ thống sản xuất, mà tôi không thể sinh sản trong môi trường phát triển:Làm thế nào để tạo lại UnicodeEncodeError?

with io.open(file_name, 'wt') as fd: 
    fd.write(data) 

Ngoại lệ:

File "/home/.../foo.py", line 18, in foo 
    fd.write(data) 

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 6400: ordinal not in range(128) 

Tôi đã cố gắng nhưng rất nhiều nhân vật lạ vào biến data.

Nhưng cho đến bây giờ tôi không thể tạo lại số UnicodeEncodeError.

Điều gì cần phải ở trong data để nhận được UnicodeEncodeError?

Cập nhật

python -c 'import locale; print locale.getpreferredencoding()' 
UTF-8 

Update2

Nếu tôi gọi locale.getpreferredencoding() qua vỏ và thông qua yêu cầu web, mã hóa là "UTF-8".

Tôi đã cập nhật xử lý ngoại lệ trong mã của mình và đăng nhập getpreferredencoding() từ một số ngày. Bây giờ nó đã xảy ra một lần nữa (đến nay tôi không thể ép buộc hoặc tái tạo điều này), và mã hóa là "ANSI_X3.4-1968"!

Tôi không có đầu mối khi mã hóa này được đặt ....

Điều này đặt vấn đề của tôi theo một hướng khác. Để lại câu hỏi này vô ích. Vấn đề của tôi bây giờ là: Mã hóa ưa thích bị thay đổi ở đâu? Nhưng đây không phải là một phần của câu hỏi này.

Xin cảm ơn, đối với tất cả những ai

+1

bạn biết đấy, không có thêm bất kỳ thông tin cho phép chúng ta tạo lại vấn đề của bạn (bạn đã biết, một [MCVE]), không có câu trả lời khác để cung cấp cho. Tôi rất hoài nghi rằng * chỉ với mã mà bạn đã hiển thị * rằng 'locale.getpreferredencoding()' thực sự là UTF-8 * khi bạn nhấn lỗi đó *. –

+0

Bạn cũng có thể chỉ cần kiểm tra mã hóa đã được chọn cho tệp; 'io.TextIOWrapper' có thuộc tính' encoding'. Nó sẽ được đặt thành ASCII trong trường hợp cụ thể này. –

Trả lời

7

Bạn đang dựa vào mã hóa mặc định cho nền tảng; khi mã hóa mặc định đó không thể hỗ trợ các ký tự Unicode bạn đang ghi vào tệp, bạn sẽ nhận được một ngoại lệ mã hóa.

Từ io.open() documentation:

encoding is the name of the encoding used to decode or encode the file. This should only be used in text mode. The default encoding is platform dependent (whatever locale.getpreferredencoding() returns), but any encoding supported by Python can be used.

Đối với tình hình cụ thể của bạn, mặc định được trả về bởi locale.getpreferredencoding() là ASCII, vì vậy bất kỳ ký tự Unicode bên ngoài phạm vi ASCII sẽ gây ra vấn đề này, U-0080 trở lên.

Lưu ý rằng ngôn ngữ được lấy từ môi trường của bạn; nếu nó là ASCII, điều đó thường có nghĩa là miền địa phương được đặt thành POSIX default locale, C.

Xác định mã hóa một cách rõ ràng:

with io.open(file_name, 'wt', encoding='utf8') as fd: 
    fd.write(data) 

tôi đã sử dụng UTF-8 là một ví dụ; những gì bạn chọn phụ thuộc hoàn toàn vào các trường hợp sử dụng của bạn và dữ liệu bạn đang cố gắng viết ra.

+0

locale.getpreferredencoding() trả về UTF-8. AFAIK mỗi chuỗi có thể được mã hóa thành utf8. Đó là lý do tại sao tôi không hiểu nội dung của "dữ liệu". – guettli

+1

@guettli: * trên hệ thống làm tăng ngoại lệ *? Bởi vì truy nguyên của bạn rõ ràng chỉ ra rằng đó là cuộc gọi 'fd.write' gây ra vấn đề này và codec duy nhất sẽ sử dụng là bộ mã hóa cho' fd'. –

+1

@guettli: đảm bảo rằng khi ngoại lệ này xảy ra, bạn nắm bắt cả hai 'repr (dữ liệu)' và 'locale.getpreferredencoding()'. Tripple-kiểm tra các giả định của bạn về những gì 'fd' là và rằng traceback thực sự trỏ đến' fd.write() '. –

0

Quấn write trong một try/except và tiết kiệm của bạn dữ liệu vào một tập tin nhị phân - bạn sẽ có thể để xem chính xác những dữ liệu nào đem lại cho bạn các vấn đề:

with io.open(file_name, 'wt') as fd: 
    try: 
     fd.write(data) 
    except UnicodeEncodeError: 
     with open('/path/to/save/error.bin', 'wb') as err: 
      err.write(data) 
     raise 
+0

Nó không phải là nếu ngoại lệ không phải là đã nói cho bạn những gì codec đang được sử dụng. Đó là vấn đề thực sự ở đây; tại sao viết là kích hoạt một mã hóa thành ASCII. Thật thú vị khi lưu ý rằng OP đã hỏi về các trình kích hoạt mã hóa ngầm ngay trước câu hỏi này: [Tại sao UnicodeEncodeError trong \ * \ * giải mã \ * \ *?] (// stackoverflow.com/q/41567720) –

1

Tôi cố gắng này để tạo lại lỗi:

with open(filename, 'wt', encoding='ascii') as fd: 
    fd.write('\xa0') 

Traceback (most recent call last):
File "test.py", line 2, in fd.write('\xa0')
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 0: ordinal not in range(128)

+0

Chắc chắn, nhưng OP không sử dụng 'encoding ='. Vậy mã hóa đến từ đâu trong trường hợp của họ? –

+0

@MartijnPieters Như OP nói trong các chú thích, 'locale.getpreferredencoding()' trả về 'utf-8' vậy điều gì đang xảy ra ở đây? – Juggernaut

+1

Tôi đã cố gắng để có thêm thông tin từ OP về điều đó. Họ không thể nhận được ngoại lệ * và * 'locale.getprefrerredencoding()' là 'UTF-8', không phải với mã họ đã đăng. Tôi đăng câu trả lời của tôi trước khi tiền thưởng được đặt, vì vậy rõ ràng OP không tin tôi về điều này. –

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