Manipulación de archivos con caracteres no ascii en XP

Oswaldo Hernández listas en soft-com.es
Mie Sep 2 15:18:40 CEST 2009


Hola a todos,

Disculpad por el rollo que va a continuación ya que este mensaje creo que es mas un desahogo que una 
consulta ya que llevo un montón de horas dándole vueltas a esto. Imagino que estará documentado en 
alguna parte, pero no lo he encontrado.

El problema: Manipulación de archivos con acentos u otros caracteres no ascii en el nombre.

Sistema: Python 2.5, Windows XP SP3
Condiguración de encoding y locale:
 >>> sys.getdefaultencoding()
'UTF-8'
 >>> sys.getfilesystemencoding()
'mbcs'
 >>> locale.getlocale()
('es_ES', 'cp1252')


1ª Parte: Abrir archivo con en nombre directamente en codigo
--------

- Intento Abrir directamente el archivo:

 >>> file = "c:\\temp\\Imágenes.txt"
 >>> file
'c:\\temp\\Im\xc3\xa1genes.txt'
 >>> open(file, "r")
Traceback (most recent call last):
   File "<input>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'c:\\temp\\Im\xc3\xa1genes.txt'

- Intento abrir condificando el nombre del archivo a cp1252:

file = "c:\\temp\\Imágenes.txt".encode("cp1252")
file
'c:\\temp\\Im\xe1genes.txt'
open(file, "r")
Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\py\shell.py", line 1160, in writeOut
     self.write(text)
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\py\shell.py", line 950, in write
     self.AddText(text)
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\stc.py", line 1425, in AddText
     return _stc.StyledTextCtrl_AddText(*args, **kwargs)
   File "c:\python25\lib\encodings\utf_8.py", line 16, in decode
     return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 22-24: invalid data

- Intento abrir definiendo la cadena como unicode

 >>> file = u"c:\\temp\\Imágenes.txt"
 >>> file
u'c:\\temp\\Im\xc3\xa1genes.txt'
 >>> open(file, "r")
Traceback (most recent call last):
   File "<input>", line 1, in <module>
IOError: [Errno 2] No such file or directory: u'c:\\temp\\Im\xc3\xa1genes.txt'

- Intento abrir convirtiendo la cadena mediante la funcion unicode()

 >>> file = "c:\\temp\\Imágenes.txt"
 >>> file
'c:\\temp\\Im\xc3\xa1genes.txt'
 >>> file = unicode(file)
 >>> file
u'c:\\temp\\Im\xe1genes.txt'
 >>> open(file, "r")
<open file u'c:\\temp\\Im\xe1genes.txt', mode 'r' at 0x01DAD218>

Funciona !!!. He tenido que convertir explicitamente con unicode(), la sintaxis u"..." no funciona.


2ª Parte: Abrir archivos con los nombres obtenidos con os.listdir()
---------

- Obtengo el nombre del archivo leyendo el directorio
 >>> dir = "c:\\temp"
 >>> archivos = os.listdir(dir)
 >>> archivos
['Im\xe1genes.txt']
 >>> file = os.path.join(dir, archivos[0])
 >>> file
'c:\\temp\\Im\xe1genes.txt'

- Intento abrir el file que ha devuelto os.listdir()

 >>> open(file, "r")
Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\py\shell.py", line 1160, in writeOut
     self.write(text)
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\py\shell.py", line 950, in write
     self.AddText(text)
   File "C:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\stc.py", line 1425, in AddText
     return _stc.StyledTextCtrl_AddText(*args, **kwargs)
   File "c:\python25\lib\encodings\utf_8.py", line 16, in decode
     return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 22-24: invalid data

- Intento convertir el nombre del archivo a unicode:

 >>> unicode(file)
Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "c:\python25\lib\encodings\utf_8.py", line 16, in decode
     return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 10-12: invalid data

- Depues de investigar un poco veo que os.listdir() ha devuelto el nombre del archivo en cp1252, 
intento decodificarlo:

 >>> file = file.decode("cp1252")
 >>> file
u'c:\\temp\\Im\xe1genes.txt'
 >>> open(file, "r")
<open file u'c:\\temp\\Im\xe1genes.txt', mode 'r' at 0x01DAD770>

Funciona !!!, os.listdir ha devuelto los nombres de archivo como str en la codificación local y es 
necesario decodificarlos.


3ª parte: Ejecución del archivos con subprocess.popen()
---------
Al ejecutarse el archivo con shell el sistema debe abrirlo con la aplicación asociada.

- Intento ejecutar el archivo obtenido con listdir() utilizando las mismas reglas que para open().

 >>> dir = "c:\\temp"
 >>> archivos = os.listdir(dir)
 >>> file = os.path.join(dir, archivos[0])
 >>> file = file.decode("cp1252")
 >>> file
u'c:\\temp\\Im\xe1genes.txt'
 >>> proc = subprocess.Popen(file, shell=True, env=os.environ.copy())
 >>> proc.poll()
1

No ha funcionado, iluso de mi.

- Intento ejecutar tal cual ha devuelto os.listdir(), es decir como str y en codificacion cp1252

 >>> dir = "c:\\temp"
 >>> archivos = os.listdir(dir)
 >>> file = os.path.join(dir, archivos[0])
 >>> file
'c:\\temp\\Im\xe1genes.txt'
 >>> proc = subprocess.Popen(file, shell=True, env=os.environ.copy())
 >>> proc.poll()
0

Funciona !!!

- Intento ahora el popen indicando directamente el archivo a ejecutar:

 >>> file = "c:\\temp\\Imágenes.txt"
 >>> proc = subprocess.Popen(file, shell=True, env=os.environ.copy())
 >>> proc.poll()
1

No funciona

- Intento convertir la cadena a unicode tal cual funcionaba con open()

 >>> file = "c:\\temp\\Imágenes.txt"
 >>> file = unicode(file)
 >>> file
u'c:\\temp\\Im\xe1genes.txt'
 >>> proc = subprocess.Popen(file, shell=True, env=os.environ.copy())
 >>> proc.poll()
1

Tampoco funciona

- Intento confertir la cadena a cp1252

 >>> file = "c:\\temp\\Imágenes.txt"
 >>> file = file.encode("cp1252")
 >>> file
'c:\\temp\\Im\xe1genes.txt'
 >>> proc = subprocess.Popen(file, shell=True, env=os.environ.copy())
 >>> proc.poll()
0

Funciona !!!


Conclusión para trabajar con archivos con caracteres no ascii en windows XP:

* open() precisa que el nombre de archivo sea una unicode.
* os.listdir() devuelve los nombres de archivo como str y en el locale
* subprocess.popen() requiere str en el locale

* No he comprobado el modulo shutil cuando hay acentos en los directorios, eso lo dejo para otro dia. :(


No se si se ha escapado algo en cuanto a la manipulación de archivos con caracteres no ascii, espero 
que este follon solo sea cosa del XP de las narices y que en linux no suceda lo mismo.


Bueno, ya me he deshaogado. Disculpad el rollo como decia al principio.

Saludos,


-- 
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es