2013-07-02 89 views
7

我有一個用UTF-8編碼寫入一些字符串的Python腳本。在我的腳本中,我主要使用str()函數來轉換爲字符串。它看起來像這樣:瞭解Python Unicode和Linux終端

mystring="this is unicode string:"+japanesevalues[1] 
#japanesevalues is a list of unicode values, I am sure it is unicode 
print mystring 

我不使用Python終端,只是標準的Linux紅帽x86_64終端。我設置終端輸出utf8字符。

如果我執行此:

#python myscript.py 
this is unicode string: カラダーズ ソフィー 

但如果我這樣做:

#python myscript.py > output 

我得到了典型的錯誤:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 253-254: ordinal not in range(128) 

這是爲什麼?

+0

在你的問題,你說的「某些字符串使用UTF-8編碼」你怎麼能確保該字符串用UTF-8編碼,你做了什麼? –

+0

@ venus.w對不起,我幫不了你。我正在讀取以UTF-8編碼的數據庫和CSV中的字符串,但我只是假設編碼實際上是UTF-8(因爲如果我打印出來,我可以正確讀取日文字符),但它們可能是實際上編碼在其他字符集,也允許日語字符。我相信有python函數可以告訴你一個字符串的編碼,甚至改變它。 – Cesc

回答

15

終端有一個字符集和Python知道,字符集是什麼,所以它會在您Unicode字符串自動解碼成字節編碼終端使用,你的情況UTF-8。

但是當你重定向,你不再使用終端。你現在只是使用Unix管道。 Unix管道沒有字符集,Python無法知道你現在想要的編碼,所以它會回落到默認的字符集。 您標記您的問題以「Python的3.x的」,但你print語法是Python 2中,所以我你實際上是使用Python 2.然後你sys.getdefaultencoding()一般'ascii',對你來說這絕對是如此懷疑。當然,你不能將日文字符編碼爲ASCII,所以你會得到一個錯誤。

你使用Python 2時,最好的辦法是在打印之前用UTF-8編碼字符串。然後重定向將起作用,並且生成的文件將爲UTF-8。這意味着,如果你的終端是其他東西,它將不起作用,但是你可以從sys.stdout.encoding得到終端編碼並使用它(當在Python 2下重定向時它將是無)。

在Python 3中,您的代碼應該按原樣運行,但需要將print mystring更改爲print(mystring)

+0

是的,它是蟒蛇2,我只是檢查,對不起。你是對的,如果我這樣做:打印mystring.encode('utf-8'),那麼我沒有問題重定向。感謝您的準確解釋。 – Cesc

+3

您也可以強制Python在使用['PYTHONIOENCODING'環境變量](http://docs.python.org/2/using/cmdline.html#envvar-PYTHONIOENCODING)管道時使用不同的編碼。 –

+0

你說'打印之前用utf-8解碼字符串',但它應該是'在打印之前將unicode編碼爲utf8編碼的字符串'(mystring.encode('utf-8'))。 – AlbertFerras

2

如果將其輸出到終端那麼Python可以檢查的$LANG值挑選一個字符集。如果您重定向,所有投注都關閉。