2012-08-16 132 views
2

我正在編寫清理Unicode文本文件(存儲爲UTF-8)的腳本,我選擇使用Python 3.x(3.2)而不是更流行的2.x,因爲3.x應該默認爲UTF-8。也許我做錯了什麼,但是看起來至少print語句並不是UTF-8的默認值。如果我嘗試打印字符串(MSG下面是一個字符串)包含特殊字符,我仍然獲得了UnicodeEncodeError這樣的:爲什麼Python 3.2中的print()似乎默認爲UTF-8?

print(label, msg) 
... in encode 
    return codecs.charmap_encode(input,self.errors,encoding_map)[0] 
UnicodeEncodeError: 'charmap' codec can't encode character '\u0968' in position 
38: character maps to <undefined> 

如果我使用的編碼()方法首先(這也很好地默認爲UTF -8),我可避免的錯誤:

print(label, msg.encode()) 

這也適用於打印對象或包含unicode字符串列表 - 這是我經常在調試的時候做的事情 - 因爲STR()似乎默認爲UTF- 8。但是我真的需要記住每次我想要打印(myobj)時使用print(str(myobj).encode())?如果是這樣,我想我可以嘗試用自己的函數來包裝它,但我對處理print()支持的所有參數置換沒有信心。

此外,我的腳本從一個文件加載正則表達式並逐一應用它們。申請編碼()之前,我是能夠打印清晰公平的控制檯的東西:

msg = 'Applying regex {} of {}: {}'.format(i, len(regexes), regex._findstr) 
print(msg) 

Applying regex 5 of 15: ^\\ge[0-9]*\b([ ]+[0-9]+\.)?[ ]* 

然而,這種崩潰如果正則表達式包含文字Unicode字符,所以我第一次申請編碼()的字符串。但現在的正則表達式是很難在屏幕上閱讀(我懷疑我可能有類似的麻煩,如果我嘗試編寫代碼,保存這些正則表達式回磁盤):

msg = 'Applying regex {} of {}: {}'.format(i, len(regexes), regex._findstr) 
print(msg.encode()) 

b'Applying regex 5 of 15: ^\\\\ge[0-9]*\\b([ ]+[0-9]+\\.)?[ ]*' 

我不是非常有經驗尚在Python中,所以我可能會誤解。任何對教程的解釋或鏈接(對於Python 3.x來說,大部分我在網上看到的都是2.x),我們將非常感激。

+0

如果您在Windows上運行,請參閱http://stackoverflow.com/questions/4942305/why-dont-scripting-languages-output-unicode-to-the-windows-console – dan04 2012-08-16 13:29:45

+1

Python 3不會默認爲UTF-8。它默認爲Unicode,但這是一個完全不同的野獸。閱讀或觀看Ned Batchelder的真棒[Pragmatic Unicode](http://bit.ly/unipain)。 – delnan 2012-08-17 02:15:12

+0

只是爲了澄清,我並沒有聲稱Python默認爲UTF-8(因爲內部表示不是'編碼'),但我認爲,因爲encode()會做,所以print()也是如此。感謝thg435澄清print()取決於輸出設備。 – 2012-12-13 16:26:35

回答

6

print不默認任何編碼,它只是使用輸出設備(如控制檯)聲稱支持的任何編碼。您的控制檯編碼似乎是非Unicode的,因此print會嘗試使用該編碼對您的Unicode字符串進行編碼,並且失敗。解決這個問題的最簡單方法是告訴控制檯使用utf8(例如在unix系統上使用export LC_ALL=en_US.UTF-8)。

+0

謝謝;這有助於。並感謝任何與相關主題相關的人,「爲什麼不將腳本語言輸出到Windows控制檯?」。之前我曾經搜索過這個問題,但沒想過在「Windows控制檯」上搜索。 – 2012-08-17 07:31:18

2

更簡單的處理方法是隻在腳本中使用unicode,並且只在需要與「外部」世界進行交互時使用編碼數據。也就是說,當你有輸入來解碼或輸出編碼。

這樣做,每次你讀東西,使用decode,每次你輸出的東西,使用encode

對於你的正則表達式,使用re.UNICODE標誌。

我知道這並不完全正確地回答你的問題,但我認爲應用這種方法應該可以讓你避免編碼問題。

+0

我不確定「更簡單」是什麼意思,因爲我說它使用無編碼打印比使用兩者更容易。另外,我還以爲我已經在我的腳本和文件中「只使用unicode」。當然,數據必須在磁盤上「編碼」。我以「utf-8」讀取文件,所以我不認爲我需要使用解碼,但到目前爲止,我沒有看到在每個打印語句中使用編碼的方法。我會看看re.UNICODE標誌。 – 2012-08-16 10:02:21

+0

我表示你可能想「只使用unicode」,因爲你的正則表達式似乎沒有使用unicode,因此表明你可能不是「只使用unicode,儘管你可能會這樣認爲。」 – 2012-08-16 12:37:48

+0

不,我的正則表達式都使用要麼是純文本(這是有效的unicode),要麼直接包含特殊字符,它們都保存在一個UTF-8文本文件中,但是我懷疑用正則表達式反斜槓標記可能會更好。我不確定 – 2012-08-17 07:21:28

相關問題