2009-06-27 22 views
17

Sono su Python 2.6 per Windows.Converti nomi di file python in Unicode

Io uso os.walk per leggere un albero di file. I file possono avere caratteri non a 7 bit (tedesco "ae" per esempio) nei loro nomi di file. Questi sono codificati nella rappresentazione di stringa interna Pythons.

Sto elaborando questi nomi di file con le funzioni della libreria Python e che non riesce a causa di una codifica errata.

Come posso convertire questi nomi di file in stringhe python corrette (unicode?)?

Ho un file "d: \ utest \ ü.txt". Passando il percorso come unicode non funziona:

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

funziona: Guardate il vostro uscita !! Sia il nome della directory u'd: \\ utest 'e il nome del file u' \ xfc.txt 'sono presentati come oggetti unicode u'blahblah' invece degli oggetti str precedenti 'blahblah'. Forse il fatto che u-con-umlaut sia rappresentato come \ xfc ti sta sbalordendo ma è lo stesso con str come con unicode e non ha nulla a che fare con il problema str/unicode. –

+0

Forse hai bisogno di amplificare "fallisce a causa di una codifica sbagliata" ... Che cosa fallisce? Come? Mostra il traceback completo e il messaggio di errore. –

risposta

45

Se si passa una stringa Unicode per os.walk(), otterrete risultati 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

tranne per il fatto che se un nome file non è modificabile, allora [puoi ottenere un test in sostituzione di Unicode in Python 2] (http://stackoverflow.com/a/22314324/4279) – jfs

1

os.walk non è specificato usare sempre os.listdir, ma né è elencato come viene gestito Unicode. Tuttavia, os.listdir fa dire:

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.

fa semplicemente utilizzando un'opera argomento Unicode per voi?

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

No, non sono codificati nella rappresentazione di stringa interna Pythons, non esiste una cosa del genere. Sono codificati nella codifica del sistema operativo/file system. Passando in unicode funziona per os.walk però.

Non so come si comporta os.walk quando i nomi dei file non possono essere decodificati, ma presumo che si otterrà una stringa, come con os.listdir(). In tal caso avrai ancora problemi in seguito. Inoltre, non tutta la libreria standard di Python 2.x accetterà i parametri unicode correttamente, quindi potrebbe essere necessario codificarli come stringhe. Quindi, il problema potrebbe essere in qualche altro posto, ma noterete se è così. ;-)

Se è necessario un maggiore controllo della decodifica, non è sempre possibile passare una stringa e quindi decodificarla con filename = nomefile.decode() come al solito.

+1

Non è il mio down, ma: Se non lo fai sappi, non dare per scontato. –

+1

Oh, mi scusi per essere più dettagliato delle altre risposte e sollevare potenziali problemi con la soluzione. –

+1

+1 per fare un'ipotesi ragionevole ma ancora affermando esplicitamente che si tratta di un'ipotesi. Un altro +1 (se potessi) per aggiungere valore alla discussione. – RichieHindle

2

un modo più diretto potrebbe essere quello di provare quanto segue: trovare la codifica del proprio file system e quindi convertirla in unicode. per esempio,

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

ad andare nella direzione opposta,

unicode_name.encode("utf-8") 
6

ero alla ricerca di una soluzione per Python 3.0 +. Lo metterà qui in caso qualcuno ne abbia bisogno.

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 
+0

Questo funziona per me almeno – ramdaz

+0

@ramdaz 1. Come dimostra l'evidenziatore della sintassi: non si dovrebbe usare la barra dispari prima della citazione di chiusura. È un 'SyntaxError' in Python. 2. Il codice nella risposta ha passato 'bytes' a' os.walk() 'e quindi i nomi dei file sono prodotti come byte. Dovresti usare Unicode (rilasciare la chiamata '.encode()'). OP è confuso. Passare Unicode è la cosa giusta su Windows. – jfs

+0

Sembra aver smesso di funzionare con Python 3.5: 'TypeError: os.scandir() non supporta il percorso dei byte su Windows, usa invece Unicode' – koppor

3
os.walk(unicode(root_dir, 'utf-8'))