2009-01-30 6 views
13

Estoy escribiendo un script que tiene que mover algún archivo, pero desafortunadamente no parece os.path juega con la internacionalización muy bien. Cuando tengo archivos nombrados en hebreo, hay problemas. Aquí hay una captura de pantalla de los contenidos de un directorio:Python's os.path asfixia en hebreo nombres de archivo

alt text http://eli.thegreenplace.net/files/temp/hebfilenameshot.png

Consideremos ahora el código que va sobre los archivos en este directorio:

files = os.listdir('test_source') 

for f in files: 
    pf = os.path.join('test_source', f) 
    print pf, os.path.exists(pf) 

La salida es:

test_source\ex True 
test_source\joe True 
test_source\mie.txt True 
test_source\__()'''.txt True 
test_source\????.txt False 

Observe cómo os.path.exists piensa que el archivo con nombre hebreo ni siquiera existe? ¿Cómo puedo solucionar esto?

ActivePython 2.5.2 en Windows XP Home SP2

Respuesta

15

Hmm, después some digging parece que cuando el suministro de OS.listdir una cadena Unicode, esto funciona un poco:

files = os.listdir(u'test_source') 

for f in files: 

    pf = os.path.join(u'test_source', f) 
    print pf.encode('ascii', 'replace'), os.path.exists(pf) 

===>

test_source\ex True 
test_source\joe True 
test_source\mie.txt True 
test_source\__()'''.txt True 
test_source\????.txt True 

algunas observaciones importantes aquí:

  • de Windows XP (como todos los derivados NT) almacena toda nombres de archivos en Unicode
  • os.listdir (y funciones similares, como os.walk) deberían Se pasará una cadena Unicode para que funcione correctamente con las rutas Unicode. He aquí una cita desde el enlace mencionado:

os.listdir(), que devuelve los nombres de archivo, plantea una cuestión: ¿debe devolver la versión Unicode de nombres de archivo, o debe devolverlo cadenas de 8 bits que contiene las versiones codificadas? os.listdir() hará las dos cosas, dependiendo de si proporcionó la ruta del directorio como una cadena de 8 bits o una cadena Unicode . Si pasa una cadena Unicode como el camino, los nombres de archivo serán decodificados utilizando la codificación del sistema de archivos y una lista de cadenas Unicode será regresaron, mientras pasa una ruta de 8 bits volverán las versiones de 8 bits de la nombres de archivo

  • Y, por último, print quiere una cadena ASCII, no Unicode, por lo que la ruta tiene que ser codificado en ASCII.
+0

print no parece ser exigente con ASCII en todos los entornos. Ver mi respuesta – PEZ

+0

imprimir no tiene ningún problema al imprimir unicode: el problema puede estar en la codificación stdout. Si la consola es unicode, no hay problema, de lo contrario se requiere una codificación explícita. – piro

+0

Eso es excelente. Debería significar que puede informar nombres de archivos sanos en Windows si imprime en un manejador de archivo con el conjunto de codificación correcto. El controlador de errores 'reemplazar' simplemente me señala la derrota. =) – PEZ

3

se ve como un problema Unicode vs ASCII - os.listdir devuelve una lista de cadenas de caracteres ASCII.

Editar: Lo intenté en Python 3.0, también en XP SP2, y os.listdir simplemente omití los nombres de archivo hebreos en lugar de enumerarlos en absoluto.

De acuerdo con los documentos, esto significa que no fue capaz de decodificarlo:

Tenga en cuenta que cuando os.listdir() devuelve una lista de cadenas , nombres de archivos que no pueden ser decodificados correctamente se omiten en lugar que elevar UnicodeError.

+0

Supongo que podría intentarlo, pero no me ayudará ya que no puedo moverme a 3.0 en este momento. Estoy seguro de que debería haber una solución para 2.5 –

1

Funciona como un encanto usando Python 2.5.1 en OS X:

subdir/bar.txt True 
subdir/foo.txt True 
subdir/עִבְרִית.txt True 

Tal vez eso significa que esto tiene que ver con Windows XP de alguna manera?

EDIT: También probé con cadenas Unicode para tratar de imitar el comportamiento de Windows mejor:

for f in os.listdir(u'subdir'): 
    pf = os.path.join(u'subdir', f) 
    print pf, os.path.exists(pf) 

subdir/bar.txt True 
subdir/foo.txt True 
subdir/עִבְרִית.txt True 

en el terminal (OS X de la aplicación de comandos del sistema) que es. El uso de IDLE todavía funcionaba pero no imprimía el nombre de archivo correctamente. Para asegurarse de que realmente es Unicode no he comprobado:

>>>os.listdir(u'listdir')[2] 
u'\u05e2\u05b4\u05d1\u05b0\u05e8\u05b4\u05d9\u05ea.txt' 
+0

, creo que tiene que ver con el hecho de que Windows almacena todos los nombres de archivos en Unicode. ver mi propia respuesta parcial –

+0

En mi máquina, también funciona con cadenas Unicode. – PEZ

+0

curioso. si solo paso pf para imprimir, arroja una excepción de codificación. debe estar esperando ascii –

0

Un signo de interrogación es el símbolo más o menos universal que se muestra cuando un carácter Unicode no se puede representar en una codificación específica. Su sesión terminal o interactiva en Windows probablemente esté usando ASCII o ISO-8859-1 o algo así. Entonces, ¿la cadena real es unicode, pero se traduce a ???? cuando se imprime en la terminal. Es por eso que funciona para PEZ, utilizando OSX.

+0

¿Puedo hacer que la pantalla del terminal windoze muestre unicode? ¿Qué hace OSX para mostrarlo bien? –