2010-01-16 12 views
12

In meiner Django-Anwendung hat ein Benutzer eine Datei mit einem Unicode-Zeichen in den Namen hochgeladen.Python os.stat und Unicode-Dateinamen

Wenn ich Dateien bin Download, ich rufe:

os.path.exists(media) 

zu testen, ob die Datei vorhanden ist. Dies wiederum scheint

st = os.stat(path) 

zu nennen, die dann mit dem Fehler sprengt:

UnicodeEncodeError: 'ascii' Codec nicht Zeichen kodieren, können u \ 'xcf' in Position 92: Ordnungszahl nicht in Bereich (128)

Was kann ich dagegen tun? Gibt es eine Option zu path.exists, um damit umzugehen?

Update: Eigentlich musste ich nur das Argument zu existieren existieren, dh.

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

Vielen Dank an alle, die geantwortet haben.

+2

Das Problem mit Ihrer Lösung, dass es nicht tragbar ist. os.path.exists sollte die Codierung basierend auf dem Gebietsschema des Betriebssystems transparent behandeln. –

Antwort

1

Kodierung vor dem Aufruf in die Kodierung des Dateisystems. Siehe das Modul locale.

+0

danke dafür. Aber ich bin mir nicht sicher, ob ich ihm folge. Willst du damit sagen, dass ich Django sagen kann, dass der Name einer hochgeladenen Datei angepasst werden sollte? Ich sehe darüber im Locale-Modul nichts. – interstar

+2

Sie müssen die Codierung des nativen Systems verwenden, um auf Dateien verweisen zu können. Probieren Sie 'locale.nl_langinfo (locale.CODESET)' aus. –

7

Ich nehme an, Sie sind in Unix. Wenn nicht, denken Sie bitte daran, in welchem ​​Betriebssystem Sie sich befinden.

Vergewissern Sie sich, dass Ihr Gebietsschema auf UTF-8 eingestellt ist. Alle modernen Linux-Systeme tun dies standardmäßig, indem sie normalerweise die Umgebungsvariable LANG auf "en_US.UTF-8" oder eine andere Sprache setzen. Stellen Sie außerdem sicher, dass Ihre Dateinamen in UTF-8 codiert sind.

Mit diesem Set gibt es keine Notwendigkeit, mit Codierungen zu stören, um auf Dateien in jeder Sprache zuzugreifen, sogar in 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' 

Wenn dies nicht funktioniert, führen Sie "locale"; Wenn die Werte "C" anstelle von "en_US.UTF-8" lauten, ist das Gebietsschema möglicherweise nicht korrekt installiert.

Wenn Sie in Windows sind, sollten Unicode-Dateinamen immer funktionieren (zumindest für die os/posix-Module), da die Unicode-Datei-API in Windows transparent unterstützt wird.

+3

Ich versuche das gleiche mit Buchstaben ß in der Konsole, und es funktioniert, aber wenn ich es in einem Skript ausführen tut es nicht, ich bekomme IOError, keine solche Datei oder Verzeichnis, und das Zeichen wurde in '\ xc3 \ codiert x9f ' – chuse

0

Ändern Sie Ihren http-Server, um das UTF-8-Gebietsschema zu verwenden. Zum Beispiel benutze ich apache2 auf CentOS. Ich änderte /etc/sysconfig/httpd Lokalisierungs-Einstellungen von 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

Das hat keine Auswirkungen für mich (Django 1.10, läuft auf Ubuntu 16.04). Ich bekomme immer noch den Fehler und kann OPs Lösung nicht verwenden, weil ich den 'os.path' Aufruf nicht mache, ist Django. – Deleet

+0

Apache-Konfiguration kann davon abhängen, welche Art von Betriebssystem Sie verwenden. Ubuntu verwendet möglicherweise einen anderen Pfad. –

1

Keine dieser Lösungen für mich gearbeitet. Allerdings habe ich die (a?) Lösung gefunden. Es gibt noch einen anderen Ort in Apache-Einstellungen, wo man die Gebietsschemaeinstellung hinzufügen muss, wenn man WSGI benutzt. Official docs are here. Fügen Sie die folgenden zwei Zeilen /etc/apache2/envvars (auf Ubuntu):

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

dann den Server neu starten. Das hat mein Problem gelöst.

0

Es ist leicht, diese Art von Fehler zu erhalten, wenn Service (z. B. Gunicorn) von Upstart ausgeführt wird.

Um das zu beheben, setzen Sie env in Emporkömmling Datei:

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