Podczas przesyłania potokowego danych wyjściowych programu w języku Python interpreter języka Python ma problem z zakodowaniem i ustawia go na Brak. Oznacza to taki program:
# -*- coding: utf-8 -*-
print u"åäö"
będzie działał dobrze, gdy będzie działał normalnie, ale zawiedzie z:
UnicodeEncodeError: Kodek „ascii” nie może zakodować znaku u '\ xa0' w pozycji 0: porządek poza zakresem (128)
gdy jest używany w sekwencji rur.
Jaki jest najlepszy sposób, aby to zadziałało podczas instalacji rurowej? Czy mogę po prostu powiedzieć mu, aby używało dowolnego kodowania powłoki / systemu plików / czegokolwiek używa?
Sugerowane do tej pory sugestie to bezpośrednia modyfikacja pliku site.py lub zakodowanie domyślnego kodowania za pomocą tego hacka:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
Czy istnieje lepszy sposób na wykonanie instalacji rurowej?
chcp 65001
przed uruchomieniem skryptu. Może to powodować problemy, ale często pomaga i nie wymaga dużo pisania (mniej niżset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
się, aby było trwałe, jeśli chcesz oszczędzać na pisaniu.Odpowiedzi:
Kod działa, gdy jest uruchamiany w skrypcie, ponieważ Python koduje dane wyjściowe do dowolnego kodowania używanego przez aplikację terminala. Jeśli korzystasz z pipingu, musisz go sam zakodować.
Ogólna zasada brzmi: zawsze używaj wewnętrznego Unicode. Dekoduj otrzymane wiadomości i koduj to, co wysyłasz.
Innym przykładem dydaktycznym jest program w języku Python do konwersji między ISO-8859-1 i UTF-8, dzięki czemu wszystko jest wielkie między nimi.
Ustawienie domyślnego kodowania systemu jest złym pomysłem, ponieważ niektóre używane moduły i biblioteki mogą polegać na tym, że jest to ASCII. Nie rób tego
źródło
sys.stdout
wydaje się przyjemniejszym sposobem.PYTHONIOENCODING
jeśli przekierowujesz standardowe wyjście skryptu w Pythonie 2.Po pierwsze, w odniesieniu do tego rozwiązania:
Nie jest praktyczne jednoznaczne drukowanie za pomocą danego kodowania za każdym razem. To byłoby powtarzalne i podatne na błędy.
Lepszym rozwiązaniem jest zmiana
sys.stdout
na początku programu, aby zakodować za pomocą wybranego kodowania. Oto jedno rozwiązanie, które znalazłem w Pythonie: Jak wybiera się sys.stdout.encoding? , w szczególności komentarz „toka”:źródło
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- automatycznie wykrywasz kodowanie terminala poprzez inspekcjęsys.stdout.encoding
, ale powinieneś wziąć pod uwagę przypadek, w którym się znajdujeNone
(tj. Gdy przekierowujesz wyjście do pliku) więc i tak potrzebujesz osobnej funkcji.Możesz spróbować zmienić zmienną środowiskową „PYTHONIOENCODING” na „utf_8”. Napisałem stronę na temat mojej próby z tym problemem .
Tl; dr na blogu:
daje Ci
źródło
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Można to zrobić z poziomu programu python, aby użytkownik nie był zmuszony do ustawiania zmiennej env.PYTHONIOENCODING
działa. Sposób interpretowania bajtów jako tekstu jest określany przez środowisko użytkownika . Twój skrypt nie powinien zakładać i dyktować środowisku użytkownika, jakiego kodowania znaków użyć. Jeśli Python nie pobierze ustawień automatycznie,PYTHONIOENCODING
można ustawić skrypt. Nie powinieneś go potrzebować, chyba że dane wyjściowe zostaną przekierowane do pliku / potoku.wykonuj zadanie, ale nie możesz ustawić go na samym pythonie ...
co możemy zrobić, to sprawdzić, czy nie jest ustawiony i powiedzieć użytkownikowi, aby ustawił go przed wywołaniem skryptu za pomocą:
Zaktualizuj, aby odpowiedzieć na komentarz: problem istnieje po prostu podczas instalacji na stdout. Testowałem w Fedorze 25 Python 2.7.13
kot b.py
działa ./b.py
uruchomiony ./b.py | mniej
źródło
sys.stdout.encoding
jest ustawiany automatycznie na podstawieLC_CTYPE
wartości ustawień regionalnych.Miałem podobny problem w zeszłym tygodniu . Łatwo było to naprawić w moim IDE (PyCharm).
Oto moja poprawka:
Zaczynając od paska menu PyCharm: Plik -> Ustawienia ... -> Edytor -> Kodowanie plików, następnie ustaw: „Kodowanie IDE”, „Kodowanie projektu” i „Domyślne kodowanie plików właściwości” WSZYSTKIE na UTF-8 i teraz działa jak urok.
Mam nadzieję że to pomoże!
źródło
Argumentowana zdezynfekowana wersja odpowiedzi Craiga McQueena.
Stosowanie:
źródło
Mógłbym to „zautomatyzować”, dzwoniąc do:
Tak, możliwe jest uzyskanie nieskończonej pętli tutaj, jeśli to „setenv” zawiedzie.
źródło
Pomyślałem, że wspomnę o czymś, z czym musiałem długo eksperymentować, zanim w końcu zrozumiałem, co się dzieje. Może to być tak oczywiste dla wszystkich tutaj, że nie zadali sobie trudu, aby o tym wspomnieć. Ale pomogłoby mi, gdyby tak zrobili, więc na tej zasadzie ...!
Uwaga: Używam Jython specjalnie, wersja 2.7, więc być może nie dotyczy to CPython ...
NB2: pierwsze dwie linie mojego pliku .py to:
Mechanizm ciągów znaków „%” (AKA „operator interpolacji”) powoduje również DODATKOWE problemy ... Jeśli domyślnym kodowaniem „środowiska” jest ASCII i spróbujesz zrobić coś takiego
Nie będziesz mieć problemów z uruchomieniem w Eclipse ... W Windows CLI (okno DOS) przekonasz się, że kodowanie to strona kodowa 850 (mój system operacyjny Windows 7) lub coś podobnego, co może obsłużyć przynajmniej europejskie znaki akcentowane, więc będę pracować.
będzie również działać.
Jeśli, OTOH, przekierujesz do pliku z CLI, standardowym kodowaniem będzie None, który będzie domyślnie ustawiony na ASCII (w moim systemie operacyjnym i tak), który nie będzie w stanie obsłużyć żadnego z powyższych wydruków ... (przerażające kodowanie błąd).
Więc możesz pomyśleć o przekierowaniu stdout za pomocą
i spróbuj uruchomić w potoku CLI do pliku ... Bardzo dziwnie, wydruk A powyżej zadziała ... Ale wydruk B powyżej spowoduje błąd kodowania! Następujące działania będą jednak działać poprawnie:
Doszedłem do wniosku (tymczasowo), że jeśli ciąg znaków, który jest określony jako ciąg Unicode przy użyciu prefiksu „u”, zostanie przesłany do mechanizmu obsługi%, wydaje się, że wiąże się to z użyciem domyślnego kodowania środowiska, niezależnie od czy ustawiłeś stdout na przekierowywanie!
Sposób, w jaki ludzie sobie z tym radzą, jest kwestią wyboru. Z zadowoleniem powitałbym eksperta od Unicode, który powiedziałby, dlaczego tak się dzieje, czy w jakiś sposób popełniłem błąd, jakie jest preferowane rozwiązanie tego problemu, czy dotyczy to również CPython , czy dzieje się to w Pythonie 3 itp. Itp.
źródło
"fréd"
jest to sekwencja bajtów, a nie ciąg Unicode, więccodecs.getwriter
opakowanie pozostawi to w spokoju. Potrzebujesz wiodącegou
lubfrom __future__ import unicode_literals
.Natrafiłem na ten problem w starszej aplikacji i trudno było ustalić, gdzie wydrukowano. Pomogłem sobie z tym hackiem:
Oprócz mojego skryptu test.py:
Zauważ, że to zmienia WSZYSTKIE wywołania drukowania, aby używały kodowania, więc Twoja konsola wydrukuje to:
źródło
W systemie Windows ten problem występował bardzo często podczas uruchamiania kodu w języku Python z edytora (takiego jak Sublime Text), ale nie w przypadku uruchamiania go z wiersza polecenia.
W takim przypadku sprawdź parametry edytora. W przypadku SublimeText
Python.sublime-build
rozwiązało to:źródło