2009-06-27 7 views
17

Estoy en Python 2.6 para Windows.Convertir nombres de archivo de python a Unicode

Uso os.walk para leer un árbol de archivos. Los archivos pueden tener caracteres que no sean de 7 bits ("ae" alemán, por ejemplo) en sus nombres de archivo. Estos están codificados en la representación de cadenas internas de pitones.

Estoy procesando estos nombres de archivo con las funciones de la biblioteca de Python y eso falla debido a una codificación incorrecta.

¿Cómo puedo convertir estos nombres de archivo a cadenas de python adecuadas (unicode?)?

Tengo un archivo "d: \ utest \ ü.txt". Pasando el camino como Unicode no funciona:

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

que hace el trabajo: Mire su salida !! Tanto el nombre de directorio u'd: \\ utest 'como el nombre de archivo u' \ xfc.txt 'se presentan como objetos unicode u'blahblah' en lugar de los objetos str anteriores 'blahblah'. Tal vez el hecho de que u-with-umlaut se represente como \ xfc te alucine, pero eso es lo mismo con str que con unicode y no tiene nada que ver con el problema str/unicode. –

+0

Quizás necesite amplificar "falla debido a una codificación incorrecta" ... ¿Qué falla? ¿Cómo? Muestra el rastreo completo y el mensaje de error. –

Respuesta

45

Si pasa una cadena Unicode a os.walk(), que obtendrá resultados 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

excepto que si un nombre de archivo no puede decodificarse, entonces [puede obtener una cadena de bytes en lugar de Unicode en Python 2] (http://stackoverflow.com/a/22314324/4279) – jfs

1

os.walk no está especificado para usar siempre os.listdir, pero tampoco aparece listado cómo se maneja Unicode. Sin embargo, os.listdir Qué dice:

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.

se limita el uso de una obra argumento Unicode para usted?

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

No, no están codificados en la representación de cadenas internas de pitones, no existe tal cosa. Están codificados en la codificación del sistema operativo/sistema de archivos. Sin embargo, al pasar en Unicode funciona para os.walk.

No sé cómo se comporta os.walk cuando los nombres de archivo no se pueden decodificar, pero supongo que obtendrá una cadena de nuevo, como con os.listdir(). En ese caso, volverás a tener problemas más adelante. Además, no toda la biblioteca estándar de Python 2.x aceptará los parámetros Unicode correctamente, por lo que puede necesitar codificarlos como cadenas de todos modos. Entonces, el problema puede estar en otro lugar, pero lo notarás si ese es el caso. ;-)

Si necesita más control de la decodificación, no siempre puede pasar una cadena y decodificarla con filename = filename.decode() como de costumbre.

+1

No es mi voto a la baja, sino: Si no lo hace Sabes, no asumas. –

+1

Oh, discúlpeme por ser más detallado que las demás respuestas y plantear posibles problemas con la solución. –

+1

+1 por hacer una suposición razonable, pero aún así declarar explícitamente que es una suposición. Otro +1 (si pudiera) para agregar valor a la discusión. – RichieHindle

2

una forma más directa podría ser intentar lo siguiente: encontrar la codificación de su sistema de archivos, y luego convertir eso a unicode. por ejemplo,

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

a ir a otro lado,

unicode_name.encode("utf-8") 
6

que estaba buscando una solución para Python 3.0 o superior. Lo pondré aquí en caso de que alguien más lo necesite.

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

Éste funciona para mí al menos – ramdaz

+0

@ramdaz 1. Como lo demuestra el resaltador de sintaxis: no debe usar una barra oblicua antes de la cita de cierre. Es un 'SyntaxError' en Python. 2. El código en la respuesta pasó 'bytes' a' os.walk() 'y, por lo tanto, los nombres de archivo se producen como bytes. Debería usar Unicode (soltar la llamada '.encode()') en su lugar. OP está confundido. Pasar Unicode es lo correcto en Windows. – jfs

+0

Parece que ha dejado de funcionar con Python 3.5: 'TypeError: os.scandir() no admite la ruta de bytes en Windows, use Unicode en su lugar' – koppor

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