2017-01-10 18 views
6

pojawia się błąd w systemie produkcyjnym, które nie rozmnażają się w środowisku programistycznym:Jak odtworzyć UnicodeEncodeError?

with io.open(file_name, 'wt') as fd: 
    fd.write(data) 

Wyjątek:

File "/home/.../foo.py", line 18, in foo 
    fd.write(data) 

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 6400: ordinal not in range(128) 

ja już próbował, ale wiele dziwnych znaków w zmiennej data.

Jednak do tej pory nie udało mi się odtworzyć modelu UnicodeEncodeError.

Co musi być w data, aby uzyskać UnicodeEncodeError?

Aktualizacja

python -c 'import locale; print locale.getpreferredencoding()' 
UTF-8 

Update2

Jeśli wywołać locale.getpreferredencoding() przez powłokę i poprzez żądanie strony internetowej, kodowanie jest "UTF-8".

Zaktualizowałem obsługę wyjątków w moim kodzie i zapisałem numer getpreferredencoding() od kilku dni. Teraz stało się to ponownie (do tej pory nie mogę tego wymusić ani odtworzyć), a kodowanie to "ANSI_X3.4-1968"!

nie mam pojęcia, gdzie to kodowanie pobiera ustawiony ....

Stawia to mój problem w innym kierunku. Pozostawienie tego pytania bezużytecznym. Mój problem jest teraz: Gdzie zmienia się preferowane kodowanie? Ale to nie jest część tego pytania.

Wielkie podziękowania dla wszystkich, którzy

+1

wiesz, bez żadnych dodatkowych informacji, które pozwala nam odtworzyć problemu (wiecie, [MCVE]), nie istnieją żadne inne odpowiedzi dać. Jestem bardzo sceptyczny, że * tylko z kodem, który pokazałeś *, że 'locale.getpreferredencoding()' jest naprawdę UTF-8 * kiedy trafisz ten błąd *. –

+0

Można również po prostu sprawdzić kodowanie wybrane dla pliku; 'io.TextIOWrapper' ma atrybut" kodowania ". W tym konkretnym przypadku zostanie ustawiony na ASCII. –

Odpowiedz

7

jesteś polegając na domyślnego kodowania dla platformy; kiedy to domyślne kodowanie nie obsługuje znaków Unicode, które zapisujesz w pliku, otrzymasz wyjątek kodowania.

Z io.open() documentation:

encoding is the name of the encoding used to decode or encode the file. This should only be used in text mode. The default encoding is platform dependent (whatever locale.getpreferredencoding() returns), but any encoding supported by Python can be used.

Dla konkretnej sytuacji, domyślnie zwrócona przez locale.getpreferredencoding() jest ASCII, więc dowolny znak Unicode spoza zakresu ASCII spowodowałoby ten problem U-0080 i do góry.

Należy pamiętać, że ustawienia regionalne są pobierane z twojego środowiska; jeśli jest to ASCII, oznacza to zazwyczaj, że ustawienie narodowe jest ustawione na POSIX default locale, C.

określić kodowanie explicite:

with io.open(file_name, 'wt', encoding='utf8') as fd: 
    fd.write(data) 

I stosowana UTF-8 jako przykład; to, co wybierasz, zależy całkowicie od przypadków użycia i danych, które próbujesz zapisać.

+0

locale.getpreferredencoding() zwraca UTF-8. AFAIK każdy ciąg może być zakodowany do utf8. Dlatego nie rozumiem treści "danych". – guettli

+1

@guettli: * w systemie, który zgłasza wyjątek *? Ponieważ twój traceback wyraźnie wskazuje, że jest to wywołanie 'fd.write', które powoduje ten problem, a jedynym kodekiem, który go użyje, jest zestaw kodowania dla' fd'. –

+1

@guettli: upewnij się, że po wystąpieniu tego wyjątku przechwycisz zarówno 'repr (dane)' oraz 'locale.getpreferredencoding()'. Tripple - sprawdź swoje założenia dotyczące tego, czym jest 'fd' i czy traceback rzeczywiście wskazuje na' fd.write() '. –

0

owinąć write w try/except i zapisać dane w pliku binarnym - będzie można zobaczyć dokładnie to, co daje ci dane zagadnienia:

with io.open(file_name, 'wt') as fd: 
    try: 
     fd.write(data) 
    except UnicodeEncodeError: 
     with open('/path/to/save/error.bin', 'wb') as err: 
      err.write(data) 
     raise 
+0

To nie jest tak, że wyjątek nie mówi już, jaki kodek jest używany. To prawdziwy problem; dlaczego zapis wyzwala kodowanie do ASCII. Warto zauważyć, że OP o implicite kodowanie uruchamia się tuż przed tym pytaniem: [Dlaczego UnicodeEncodeError podczas \ * \ * dekodowania \ * \ *?] (// stackoverflow.com/q/41567720) –

1

Próbowałem to do odtworzenia błąd:

with open(filename, 'wt', encoding='ascii') as fd: 
    fd.write('\xa0') 

Traceback (most recent call last):
File "test.py", line 2, in fd.write('\xa0')
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 0: ordinal not in range(128)

+0

Oczywiście, ale OP nie używa "kodowania =". Skąd więc pochodzi kodowanie w ich przypadku? –

+0

@MartijnPieters Jak mówi OP w komentarzach, 'locale.getpreferredencoding()' zwraca 'utf-8', więc co się tutaj dzieje? – Juggernaut

+1

Próbowałem uzyskać więcej informacji z OP o tym. Nie mogą uzyskać tego wyjątku * i * 'locale.getprefrerredencoding()' jest 'UTF-8', a nie z kodem, który zamieścili. Wysłałem odpowiedź przed przyznaniem nagrody, więc najwyraźniej PO nie wierzy mi w to. –

Powiązane problemy