2015-02-08 73 views
1

另一個人無法找到正確的魔法咒語來讓Python打印UTF-8字符。'ascii'編解碼器在使用Python閱讀時無法編碼錯誤JSON

我有一個JSON文件。 JSON文件包含字符串值。其中一個字符串值包含字符「à」。我有一個Python程序讀入JSON文件並打印一些字符串。有時當程序試圖打印包含「à」的字符串時,我得到錯誤

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

這很難重現。有時一個稍微不同的程序可以打印字符串「à」。只包含此字符串的較小JSON文件不會出現問題。如果我圍繞代碼開始噴灑encode('utf-8')decode('utf-8'),它會以不可預知的方式改變發生的事情。我無法創建展示此問題的最小代碼片段和輸入。

我像這樣加載JSON文件。

with codecs.open(filename, 'r', 'utf-8') as f: 
    j = json.load(f) 

我會拿出這樣的違規字符串。

s = j['key'] 

後來我做了prints作爲它的一部分,看到了錯誤。

我敢肯定,原始文件是UTF-8,因爲在交互式命令行

codecs.open(filename, 'r', 'utf-8').read() 

返回一個字符串,但

codecs.open(filename, 'r', 'ascii').read() 

給出了關於不作爲ASCII編碼解碼器的錯誤能夠解碼這樣一個字節。以字節爲單位的文件大小與由wc -c返回的字符數相同,並且我沒有看到其他任何看起來像非ASCII字符的字符,所以我懷疑問題完全在於這個高位ASCII「à」。

我沒有在我的代碼中對str()進行任何明確的調用。

我已經通過Python Unicode HOWTO多次。我知道我應該「夾心」unicode處理。我想我正在做這件事,但顯然我仍然有一些誤解。

大部分我很困惑,因爲好像我在codecs.open調用中指定'utf-8',所有事情都應該以UTF-8發生。我不明白ASCII編解碼器仍然如何潛入。

我在做什麼錯?我如何去調試呢?


編輯:用於代替codecsio模塊。同樣的結果。


編輯:我沒有一個最小的例子,但至少我有一個最小的攝製場景。

我正在打印從導致問題的JSON中的字符串派生的對象。所以下面給出了一個錯誤。

print(myobj) 

(請注意,我用的from __future__ import print_function儘管這似乎不有所作爲。)

我對象的__str__函數的返回值不修復該錯誤的末尾把一個encode('utf-8')。不過,將打印線更改爲此。

print("%s" % myobj) 

這看起來不對我。我希望這兩個打印電話是等同的。


我可以做sys.setdefaultencoding hack使這項工作:

import sys 
reload(sys) 
sys.setdefaultencoding("UTF-8") 

但是,這顯然是一個壞主意,可以使Python故障在其他方面。

這樣做的正確方法是什麼?我試過

env PYTHONIOENCODING=UTF-8 ./myscript.py 

但這並沒有奏效。 (不出所料,因爲問題是默認編碼,而不是io編碼。)

+0

什麼是'print(repr(myobj))'? – jfs 2015-02-08 22:55:24

+0

print(repr(myobj))不會引發錯誤。它按預期打印repr字符串。 (例如,轉義「\ n」而不是換行符)。 – 2015-02-10 17:35:01

+0

我問過它是什麼(導致問題的對象),而不是'repr(myobj)'是否導致錯誤(不應該)。你使用自定義對象(自定義'__unicode__','__str__')來解析json嗎?爲什麼? – jfs 2015-02-10 20:37:48

回答

3

當您直接寫入文件或將stdout重定向到文件或管道時,默認編碼爲ASCII,並且必須在編寫Unicode字符串之前進行編碼他們。隨着打開的文件句柄,你可以設置一個編碼,使其自動發生,但print你必須使用encode()方法。

print s.encode('utf-8') 

建議使用較新的io模塊代替codecs,因爲它具有改進的實現,是向前Py3.x open()兼容。

+0

在打印之前,您應該*不*編碼Unicode。不要在腳本中硬編碼環境的字符編碼。設置適當的區域設置(LANG,LC_CTYPE,LC_ALL)和/或'PYTHONIOENCODING' envvar。 – jfs 2015-02-08 23:21:18

相關問題