2017-01-10 29 views
6

我在生產系統中,這是我不能在開發環境中重現得到一個錯誤:如何重現UnicodeEncodeError?

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

例外:

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) 

我已經嘗試過,但很多奇怪的字符到變量data

但是到目前爲止,我無法複製UnicodeEncodeError

什麼需要在data得到UnicodeEncodeError

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

UPDATE2

如果通過殼和經由web請求調用locale.getpreferredencoding(),編碼是 「UTF-8」。

我在我的代碼中更新了我的異常處理,並在幾天後記錄了getpreferredencoding()。現在它再次發生(到現在爲止我無法強制或重現此),並且編碼是「ANSI_X3.4-1968」!

我不知道哪裏該編碼獲取設置....

這使我的問題變成一個不同的方向。離開這個問題沒用。我現在的問題是:首選編碼在哪裏被修改?但這不是這個問題的一部分。

非常感謝你們,所有誰

+1

你知道,沒有任何更多的信息,讓我們重現您的問題(你知道,一個[MCVE]),還有沒有其他的回答來給。我非常懷疑,*只有你顯示的代碼*當locale.getpreferredencoding()實際上是UTF-8 *時,你遇到那個錯誤*。 –

+0

您也可以檢查爲文件選擇的編碼; 'io.TextIOWrapper'有一個'encoding'屬性。在這個特定的情況下它將被設置爲ASCII。 –

回答

7

你是依靠該平臺的默認編碼;當該默認編碼不支持您正在寫入該文件的Unicode字符時,您將收到一個編碼異常。

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.

爲了您的具體情況,由locale.getpreferredencoding()返回默認爲ASCII,所以ASCII範圍之外的任何Unicode字符會導致此問題,U-0080及以上。

請注意,語言環境取自您的環境;如果它是ASCII,那通常意味着語言環境設置爲POSIX default locale, C

指定明確的編碼:

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

我用UTF-8作爲一個例子;您選擇的內容完全取決於您的用例以及您試圖寫出的數據。

+0

locale.getpreferredencoding()返回UTF-8。 AFAIK每個字符串都可以編碼爲utf8。這就是爲什麼我不瞭解「數據」的內容。 – guettli

+1

@guettli:引發異常的系統* *?因爲你的回溯清楚地表明它是導致這個問題的'fd.write'調用,並且唯一使用的編解碼器是爲'fd'設置的編碼。 –

+1

@guettli:確保發生這種異常時,您同時捕獲'repr(data)'和'locale.getpreferredencoding()'。 Tripple-check檢查你對'fd'是什麼的假設以及回溯是否真的指向'fd.write()'。 –

0

包裝你writetry/except並保存數據轉換成二進制文件 - 你可以看到什麼樣的數據是給你的問題:

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

這並不是說該異常不是已經告訴你正在使用哪個編解碼器。這是真正的問題。爲什麼寫作會觸發ASCII編碼。有趣的是,OP詢問了在這個問題之前的隱式編碼觸發器:[爲什麼UnicodeEncodeError在解碼* * *?](// stackoverflow.com/q/41567720) –

1

我想這重現錯誤:

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

當然,但是OP沒有使用'encoding ='。那麼編碼來自哪裏呢? –

+0

@MartijnPieters正如OP在評論中所說的,'locale.getpreferredencoding()'返回'utf-8',所以這裏發生了什麼? – Juggernaut

+1

我試圖從OP那裏獲得更多信息。他們無法獲得該異常*和*'locale.getprefrerredencoding()'爲'UTF-8',而不是他們發佈的代碼。我在發佈獎金之前發佈了我的答案,顯然OP不相信我。 –