2016-08-19 28 views
0

我知道有很多關於Python 2上的「UTF-8」編碼問題的討論,但我無法找到解決方案給我的問題到目前爲止。我目前正在創建一個腳本來獲取文件的名稱並用xlwt將其鏈接,以便通過電子表格中的點擊訪問該文件。問題是,這些文件的一些名稱包含非ASCII字符。Python 2.7「拉丁-1」編碼,而不是「UTF-8」

問題1

我用下面的一行來檢索文件的名稱。順便說一句,文件夾中只有一個文件。

>>f = filter(os.path.isfile, os.listdir(tmp_path))[0] 

然後

>>print f 
'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 
>>print sys.stdout.encoding 
'UTF-8' 
>>f.decode("UTF-8") 
*** UnicodeDecodeError: 'utf8' codec can't decode byte 0xe7 in position 76: invalid continuation byte 

從這裏瀏覽的討論,我意識到, 「\ XE7 \ xe3o」 不是 「UTF-8」 編碼。運行下面的行似乎支持這一點。

>>f.decode("latin-1") 
u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 

我的問題是那麼,爲什麼變量f正在編碼「Latin-1的」當系統編碼設置爲「UTF-8」?

問題2

雖然f.decode(「拉丁-1」)給我我想要的輸出,我仍然無法將可變電源到電子表格中的超鏈接功能。

>>data.append(["File", xlwt.Formula('HYPERLINK("%s";"%s")' % (os.path.join(dl_path,f.decode("latin-1")),f.decode("latin-1")))]) 
*** FormulaParseException: can't parse formula HYPERLINK("u'H:\\Mad Lab\\SE Doc Crawler\\bovespa\\download\\521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's;"u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's) 

顯然,最後的雙引號被吃掉了,被一個「's」後綴取代。有人可以幫助解釋這裏發生了什麼嗎? 0.0

哦,如果有人可以建議上述問題2的解決方案,那麼我將非常感謝 - 因爲你會把我的週末從痛苦中拯救出來!

在此先感謝所有!

+0

文件系統編碼總是可以與區域設置(stdout和stdin編碼)不同。而是看看'sys.getfilesystemencoding()'。 –

+0

你能告訴我什麼操作系統,如果你使用控制檯或IDLE,PyCharm,Intellij或Eclipse等IDE,那麼我可以給你一個特定的答案嗎? –

+0

@MartijnPieters sys.getfilesystemencoding()拋出「mbcs」 – kerwei

回答

0

歡迎來到編碼混亂的世界!至少有文件編碼,終端編碼和文件名編碼需要處理,而且三者可能會有所不同。

在Python 2.x中,目標是從編碼的str中獲取一個Unicode字符串(與str不同)。問題是你並不總是知道用於str的編碼,所以很難解碼它。

當使用listdir()獲取文件名,有一個證明,但常常被忽視的怪癖 - 如果你傳遞一個strlistdir()你得到編碼str回來了。這些將根據您的語言環境進行編碼。在Windows上,這些將是一個8位字符集,如windows-1252

或者,也可以通過listdir()代替Unicode字符串。

E.g.

os.listdir(u'C:\\mydir') 

u前綴

這將返回正確解碼Unicode文件名。在Windows和OS X上,只要您的環境語言環境未被混淆,這就非常可靠。

在你的情況,listdir()將返回:

u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 

同樣要注意u前綴。您現在可以將其打印到您的PyCharm控制檯,而無需修改。

E.g.

f = filter(os.path.isfile, os.listdir(tmp_path))[0] 
print f 
+0

感謝您的解釋!我正在閱讀文件夾中的文件,因此我沒有選擇使用帶字符串文字的'u'前綴。無論如何,你的回答指向了正確的方向,並且由於[鏈接](http://nedbatchelder.com/text/unipain.html),我想我現在對編碼主題有了更好的理解。我會將其標記爲解決方案。 – kerwei

+0

沒問題。關鍵是,你第一次通過'listdir()'列出你想要列出的目錄時,可以使用'u'''或其他方式創建的Unicode對象。結果將是Unicode。 –

0

至於第二個問題,我沒有深入研究,但只是打印輸出爲unicode字符串,而不是xlwt對象,由於時間的限制。我能夠繼續這個項目,但是沒有理解這裏出了什麼問題。從這個意義上說,上面的兩個問題已經得到了回答。