2010-01-16 18 views
12

W mojej aplikacji Django użytkownik załadował plik z nazwą Unicode w nazwie.Python os.stat i nazwy plików Unicode

Kiedy jestem pobierania plików, dzwonię:

os.path.exists(media) 

aby sprawdzić, czy plik istnieje. To z kolei wydaje się nazywają

st = os.stat(path) 

Które następnie wysadza z błędem:

UnicodeEncodeError: „ascii” codec nie może kodować charakter u „\ XCF” w pozycji 92: nie porządkowej w zakres (128)

Co mogę z tym zrobić? Czy istnieje opcja path.exists do obsługi tego?

Aktualizacja: Właściwie wszystko, co musiałem zrobić, to zakodować argument, że istnieje, tj.

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

Dziękuję wszystkim, którzy odpowiedzieli.

+2

Problem z rozwiązania jest to, że jej nie przenośne. os.path.exists powinien jawnie obsługiwać kodowanie w zależności od ustawień regionalnych systemu operacyjnego. –

Odpowiedz

1

Zakodować kodowanie systemu plików przed wywołaniem. Zobacz moduł locale.

+0

dzięki za to. Ale nie jestem pewien, czy podążam. Czy mówisz, że mogę powiedzieć Django, że nazwa przesłanego pliku powinna zostać zaadaptowana? Nic nie widzę w module ustawień regionalnych. – interstar

+2

Musisz użyć kodowania rodzimego systemu, aby odnieść się do plików. Wypróbuj 'locale.nl_langinfo (locale.CODESET)'. –

7

Zakładam, że jesteś w systemie Unix. Jeśli nie, pamiętaj, aby powiedzieć, w którym systemie operacyjnym jesteś.

Upewnij się, że twoje ustawienia narodowe są ustawione na UTF-8. Wszystkie nowoczesne systemy Linux robią to domyślnie, zwykle ustawiając zmienną środowiskową LANG na "en_US.UTF-8" lub inny język. Upewnij się także, że twoje nazwy plików są kodowane w UTF-8.

Przy tym zestawie nie ma potrzeby wprowadzania zmian z kodowaniem, aby uzyskać dostęp do plików w dowolnym języku, nawet w Pythonie 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' 

Jeśli to nie działa, uruchom "ustawienia regionalne"; jeśli wartością jest "C" zamiast en_US.UTF-8, możesz nie mieć poprawnie zainstalowanych ustawień narodowych.

Jeśli jesteś w systemie Windows, myślę, że nazwy plików w Unicode powinny zawsze działać (przynajmniej dla modułów os/posix), ponieważ interfejs API pliku Unicode w systemie Windows jest obsługiwany w sposób przezroczysty.

+3

Próbuję to samo z literą ß w konsoli, i to działa, ale gdy wykonuję ją w skrypcie, to nie, otrzymuję IOError, nie ma takiego pliku lub katalogu, a znak został zakodowany do "\ xc3 \" x9f ' – chuse

0

Zmień swój serwer http, aby używać ustawień regionalnych UTF-8. Na przykład używam apache2 na CentOS. Zmieniłem /etc/sysconfig/httpd ustawień regionalnych przez 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

Nie ma to dla mnie żadnego efektu (Django 1.10, działa na Ubuntu 16.04). Nadal dostaję błąd i nie mogę użyć rozwiązania OP, ponieważ nie robię wywołania 'os.path', Django. – Deleet

+0

Konfiguracja Apache może zależeć od używanego systemu operacyjnego. Ubuntu może używać innej ścieżki. –

1

Żadne z tych rozwiązań nie pracował dla mnie. Jednak znalazłem rozwiązanie (a?). W ustawieniach Apache jest jeszcze jedno miejsce, w którym trzeba dodać ustawienie regionalne, jeśli używa się WSGI. Official docs are here. Dodaj następujące dwie linie do /etc/apache2/envvars (na Ubuntu):

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

Następnie należy zrestartować serwer. To rozwiązało mój problem.

0

Łatwo jest uzyskać taki błąd podczas uruchamiania usługi (np. Gunicorn) od Upstart.

Aby to naprawić, ustawić env w upstart pliku:

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