2009-06-27 129 views
17

我在Python 2.6 for Windows上。將python文件名轉換爲unicode

我使用os.walk來讀取文件樹。文件的文件名可能包含非7位字符(例如德語「ae」)。這些以Pythons內部字符串表示形式編碼。

我正在使用Python庫函數處理這些文件名,並且由於編碼錯誤而失敗。

如何將這些文件名轉換爲正確的(unicode?)python字符串?

我有一個文件「d:\ utest \ü.txt」。傳遞路徑爲Unicode不工作:

>>> list(os.walk('d:\\utest')) 
[('d:\\utest', [], ['\xfc.txt'])] 
>>> list(os.walk(u'd:\\utest')) 
[(u'd:\\utest', [], [u'\xfc.txt'])] 
+2

它的工作:看看你輸出!目錄名稱u'd:\\ utest'和文件名稱u'\ xfc.txt'都以unicode對象u'blahblah'的形式出現,而不是以前的str對象'blahblah'。也許u-with-umlaut表示爲\ xfc的事實讓你感到驚訝,但這與str和unicode一樣,並且與str/unicode問題無關。 – 2009-06-27 10:42:23

+0

也許你需要放大「由於編碼錯誤而失敗」......什麼失敗了?怎麼樣?顯示完整的回溯和錯誤消息。 – 2009-06-27 12:07:56

回答

45

如果你傳遞一個Unicode字符串os.walk(),你會得到Unicode的結果:

>>> list(os.walk(r'C:\example'))   # Passing an ASCII string 
[('C:\\example', [], ['file.txt'])] 
>>> 
>>> list(os.walk(ur'C:\example'))  # Passing a Unicode string 
[(u'C:\\example', [], [u'file.txt'])] 
+0

除了如果一個文件名是undecodable然後[你可以得到一個字符串,而不是Unicode在Python 2](http://stackoverflow.com/a/22314324/4279) – jfs 2015-05-17 19:21:09

1

os.walk未指定總是使用os.listdir,但它也沒有列出如何處理Unicode。然而,os.listdir確實說:

Changed in version 2.3: On Windows NT/2k/XP and Unix, if path is a Unicode object, the result will be a list of Unicode objects. Undecodable filenames will still be returned as string objects.

是否簡單地使用你一個Unicode論證工作?

for dirpath, dirnames, filenames in os.walk(u"."): 
    print dirpath 
    for fn in filenames: 
    print " ", fn 
1

不,它們不用Pythons內部字符串表示形式編碼,沒有這樣的事情。它們以操作系統/文件系統的編碼進行編碼。儘管傳入unicode可以用於os.walk。

我不知道當文件名無法解碼時os.walk的行爲如何,但我認爲你會得到一個字符串,就像os.listdir()一樣。在那種情況下,你以後會再次遇到問題。另外,並不是所有的Python 2.x標準庫都能夠正確接受unicode參數,所以您可能需要將它們編碼爲字符串。所以,這個問題實際上可能在其他地方,但如果是這樣的話,你會注意到。 ;-)

如果你需要更多的解碼控制,你不能總是傳遞一個字符串,然後像往常一樣用 filename = filename.decode() 解碼。

+1

不是我的投票,但:如果你不知道,不要假設。 – 2009-06-27 10:30:54

2

更直接的方法可能是嘗試以下操作 - 找到您的文件系統的編碼,然後將其轉換爲unicode。例如,

unicode_name = unicode(filename, "utf-8", errors="ignore") 

走另一條路,

unicode_name.encode("utf-8") 
6

我一直在尋找的Python 3.0+的解決方案。將在這裏把它放在別人需要的地方。

rootdir = r'D:\COUNTRY\ROADS\' 
fs_enc = sys.getfilesystemencoding() 
for (root, dirname, filename) in os.walk(rootdir.encode(fs_enc)): 
    # do your stuff here, but remember that now 
    # root, dirname, filename are represented as bytearrays 
3
os.walk(unicode(root_dir, 'utf-8'))