2010-01-16 19 views
12

En mi aplicación Django, un usuario ha cargado un archivo con un carácter Unicode en el nombre.Python os.stat y nombres de archivo unicode

Cuando estoy descargando archivos, estoy llamando:

os.path.exists(media) 

para probar que el archivo está allí. Esto, a su vez, parece llamar

st = os.stat(path) 

Que luego explota con el error:

UnicodeEncodeError: códec 'ascii' no puede codificar caracteres u '\ xcf' en la posición 92: no ordinal rango (128)

¿Qué puedo hacer al respecto? ¿Existe una opción para path.exists para manejarlo?

Actualización: En realidad, todo lo que tuve que hacer fue codificar el argumento para que existiera, es decir.

os.path.exists(media.encode('utf-8') 

Gracias a todos los que respondieron.

+2

El problema con su solución es que no es portátil. os.path.exists debe manejar de forma transparente la codificación en función de la configuración regional del sistema operativo. –

Respuesta

1

Codifique la codificación del sistema de archivos antes de llamar. Vea el módulo locale.

+0

gracias por esto. Pero no estoy seguro de seguir. ¿Estás diciendo que puedo decirle a Django que se debe adaptar el nombre de un archivo cargado? No veo nada sobre esto en el módulo de configuración regional. – interstar

+2

Tiene que usar la codificación del sistema nativo para referirse a los archivos. Pruebe 'locale.nl_langinfo (locale.CODESET)'. –

7

Supongo que estás en Unix. De lo contrario, recuerde indicar en qué sistema operativo se encuentra.

Asegúrese de que su configuración regional esté configurada en UTF-8. Todos los sistemas Linux modernos hacen esto de forma predeterminada, por lo general estableciendo la variable de entorno LANG en "en_US.UTF-8" u otro idioma. Además, asegúrese de que sus nombres de archivo estén codificados en UTF-8.

Con ese conjunto, no hay necesidad de meterse con las codificaciones para acceder a los archivos en cualquier idioma, incluso en Python 2.x.

[~/test] echo $LANG 
en_US.UTF-8 
[~/test] echo testing > 漢字 
[~/test] python2.6 
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> os.stat("漢字") 
posix.stat_result(st_mode=33188, st_ino=548583333L, st_dev=2049L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=8L, st_atime=1263634240, st_mtime=1263634230, st_ctime=1263634230) 
>>> os.stat(u"漢字") 
posix.stat_result(st_mode=33188, st_ino=548583333L, st_dev=2049L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=8L, st_atime=1263634240, st_mtime=1263634230, st_ctime=1263634230) 
>>> open("漢字").read() 
'testing\n' 
>>> open(u"漢字").read() 
'testing\n' 

Si esto no funciona, ejecute "locale"; si los valores son "C" en lugar de en_US.UTF-8, es posible que no tenga la configuración regional instalada correctamente.

Si está en Windows, creo que los nombres de archivo Unicode siempre deberían funcionar (al menos para los módulos os/posix), ya que la API de archivos Unicode en Windows se admite de forma transparente.

+3

Intento lo mismo con ß carta en la consola, y funciona, pero cuando ejecuto en un script no lo hace, me sale IOError, no existe tal archivo o directorio, y el personaje ha sido codificado a '\ xc3 \ x9f ' – chuse

0

Cambie su servidor http para usar la configuración regional UTF-8. Por ejemplo, uso apache2 en CentOS. Cambié/sysconfig/httpd configuración local /etc por HTTPD_LANG:

# CentOS use /etc/sysconfig/httpd to config environment variables. 
# 
# By default, the httpd process is started in the C locale; to 
# change the locale in which the server runs, the HTTPD_LANG 
# variable can be set. 
# 
# HTTPD_LANG=C 
HTTPD_LANG=en_US.UTF-8 # you can change to your locale. 
+0

Esto no tiene ningún efecto para mí (Django 1.10, que se ejecuta en Ubuntu 16.04). Aún recibo el error y no puedo usar la solución de OP porque no estoy haciendo la llamada 'os.path', Django sí. – Deleet

+0

La configuración de Apache puede depender del tipo de sistema operativo que utilice. Ubuntu puede usar una ruta diferente. –

1

Ninguna de estas soluciones trabajó para mí. Sin embargo, encontré la solución (a?). Todavía hay otro lugar en la configuración de Apache donde uno tiene que agregar la configuración regional si uno usa WSGI. Official docs are here. Añadir las dos líneas siguientes a /etc/apache2/envvars (en Ubuntu):

export LANG='en_US.UTF-8' 
export LC_ALL='en_US.UTF-8' 

a continuación, reinicie el servidor. Esto resolvió mi problema.

0

Es fácil obtener este tipo de error cuando se ejecuta el servicio (por ejemplo, gunicorn) desde Upstart.

Para corregir esto, establecer env en el archivo recién llegado:

env LANG=en_US.UTF-8 
env LC_CTYPE=en_US.UTF-8 
env LC_ALL=en_US.UTF-8