Ustawianie poprawnego kodowania podczas przesyłania stdout w Pythonie
Podczas przesyłania wyjścia programu Pythona, interpreter Pythona jest zdezorientowany co do kodowania i ustawia go na None. Oznacza to taki program:
# -*- coding: utf-8 -*-
print u"åäö"
Będzie działać poprawnie, gdy zostanie uruchomiony normalnie, ale nie z:
UnicodeEncodeError: 'ASCII' kodek nie może zakodować znaku u '\xa0 ' W POZYCJI 0: porządkowy nie w zakresie (128)
W przypadku użycia w sekwencji rur.
Jaki jest najlepszy sposób, aby to działało podczas orurowania? Czy mogę mu powiedzieć, żeby używał czegokolwiek kodowanie powłoki / systemu plików / czego używa?
Sugestie, które do tej pory widziałem, to zmodyfikowanie twojego site.py bezpośrednio lub hardcoding 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 orurowania? 10 answers
Twój kod działa, gdy jest uruchamiany w skrypcie, ponieważ Python koduje wyjście do dowolnego kodowania używanego przez Twoją aplikację terminalową. Jeśli używasz orurowania, musisz to zakodować samodzielnie.
Regułą jest: Zawsze używaj Unicode wewnętrznie. Odszyfruj to, co otrzymujesz i Zakoduj to, co wysyłasz.
# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')
Innym dydaktycznym przykładem jest program Pythona do konwersji pomiędzy ISO-8859-1 i UTF-8, dzięki czemu wszystko pomiędzy nimi jest pisane wielkimi literami.
import sys
for line in sys.stdin:
# Decode what you receive:
line = line.decode('iso8859-1')
# Work with Unicode internally:
line = line.upper()
# Encode what you send:
line = line.encode('utf-8')
sys.stdout.write(line)
Ustawienie domyślnego kodowania systemu to zły pomysł, ponieważ niektóre moduły i biblioteki, których używasz, mogą polegać na tym, że jest to ASCII. Nie rób tego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 18:30:18
Po pierwsze, odnośnie tego rozwiązania:
# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')
Jawne drukowanie z danym kodowaniem za każdym razem jest niepraktyczne. 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 na Pythonie: jak jest sys.stdout.kodowanie wybrane?, w szczególności komentarz "toka":
import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-23 02:49:37
Możesz spróbować zmienić zmienną środowiskową "PYTHONIOENCODING" na " utf_8."Napisałem stronę O mojej Gehennie z tym problemem .
Tl;dr Z wpisu na blogu:
import sys, locale, os
print(sys.stdout.encoding)
print(sys.stdout.isatty())
print(locale.getpreferredencoding())
print(sys.getfilesystemencoding())
print(os.environ["PYTHONIOENCODING"])
print(chr(246), chr(9786), chr(9787))
Daje
utf_8
False
ANSI_X3.4-1968
ascii
utf_8
ö ☺ ☻
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-05 01:02:49
export PYTHONIOENCODING=utf-8
Wykonaj zadanie, ale nie możesz ustawić go na samym Pythonie ...
To co możemy zrobić to zweryfikować czy nie jest ustawione i powiedzieć użytkownikowi aby ustawił je przed wywołaniem skryptu za pomocą:
if __name__ == '__main__':
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
Update to reply to the comment: problem po prostu istnieje podczas orurowania na stdout . Testowałem w Fedorze 25 Python 2.7.13
python --version
Python 2.7.13
Kot b.py
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys
print sys.stdout.encoding
Bieganie ./b.py
UTF-8
Bieganie ./b.py / less
None
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 15:58:26
Miałem podobny problem w zeszłym tygodniu . To było łatwe do naprawienia w moim IDE (PyCharm).
Oto moja poprawka:
Począwszy od paska menu PyCharm: Plik - > Ustawienia... - >Edytor - > kodowanie plików, następnie Ustaw: "kodowanie IDE", "kodowanie projektu" i "domyślne kodowanie dla plików właściwości" wszystko do UTF-8 i teraz działa jak urok.
Mam nadzieję, że to pomoże!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-21 02:54:18
Dyskusyjna Wersja odpowiedzi Craiga McQueena.
import sys, codecs
class EncodedOut:
def __init__(self, enc):
self.enc = enc
self.stdout = sys.stdout
def __enter__(self):
if sys.stdout.encoding is None:
w = codecs.getwriter(self.enc)
sys.stdout = w(sys.stdout)
def __exit__(self, exc_ty, exc_val, tb):
sys.stdout = self.stdout
Użycie:
with EncodedOut('utf-8'):
print u'ÅÄÖåäö'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-13 10:24:12
Mógłbym "zautomatyzować" to wywołaniem do:
def __fix_io_encoding(last_resort_default='UTF-8'):
import sys
if [x for x in (sys.stdin,sys.stdout,sys.stderr) if x.encoding is None] :
import os
defEnc = None
if defEnc is None :
try:
import locale
defEnc = locale.getpreferredencoding()
except: pass
if defEnc is None :
try: defEnc = sys.getfilesystemencoding()
except: pass
if defEnc is None :
try: defEnc = sys.stdin.encoding
except: pass
if defEnc is None :
defEnc = last_resort_default
os.environ['PYTHONIOENCODING'] = os.environ.get("PYTHONIOENCODING",defEnc)
os.execvpe(sys.argv[0],sys.argv,os.environ)
__fix_io_encoding() ; del __fix_io_encoding
Tak, możliwe jest uzyskanie nieskończonej pętli, jeśli ten "setenv" zawiedzie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-15 10:08:10
Pomyślałem, że wspomnę o czymś, z czym musiałem długo eksperymentować, zanim w końcu zdałem sobie sprawę, co się dzieje. To może być tak oczywiste dla wszystkich tutaj, że nie pofatygowali się wspomnieć o tym. Ale pomogłoby mi, gdyby tak było, więc na tej zasadzie...!
NB: używam Jython w szczególności v 2.7, więc prawdopodobnie może to nie dotyczyć CPython...
NB2: pierwsze dwie linijki mojego pliku. py tutaj są:
# -*- coding: utf-8 -*-
from __future__ import print_function
Mechanizm konstrukcji łańcuchów " % "(AKA" operator interpolacji") powoduje również dodatkowe problemy... Jeśli domyślnym kodowaniem "environment" jest ASCII i próbujesz zrobić coś w stylu
print( "bonjour, %s" % "fréd" ) # Call this "print A"
Nie będziesz miał trudności z uruchomieniem w Eclipse... W Windows CLI (DOS window) znajdziesz, że kodowanie to strona kodowa 850 (mój system operacyjny Windows 7) lub coś podobnego, które może obsługiwać Europejskie znaki akcentowane przynajmniej, więc będzie praca.
print( u"bonjour, %s" % "fréd" ) # Call this "print B"
Będzie również działać.
Jeśli, OTOH, skierujesz Plik z CLI, kodowanie stdout będzie None, które domyślnie będzie ASCII (w moim systemie operacyjnym), które nie będzie w stanie obsłużyć żadnego z powyższych wydruków... (bał błąd kodowania).
Więc możesz pomyśleć o przekierowaniu swojego stdout za pomocą
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
I spróbuj uruchomić w CLI rurociągu do pliku... Bardzo dziwne, Wydruk powyżej zadziała... Ale Wydruk B powyżej spowoduje błąd kodowania! Na następujące będą jednak działać OK:
print( u"bonjour, " + "fréd" ) # Call this "print C"
Wniosek, do którego doszedłem (tymczasowo) jest taki, że jeśli ciąg znaków, który jest określony jako Unicode ciąg znaków z przedrostkiem "u" jest przesyłany do mechanizmu obsługi%, wydaje się, że wiąże się z użyciem domyślnego kodowania środowiska, niezależnie od tego, czy Ustawiłeś stdout na redirect!
To, jak ludzie sobie z tym radzą, jest kwestią wyboru. Zapraszam eksperta Unicode do powiedzenia dlaczego tak się dzieje, czy mam pomyliłem się w jakiś sposób, jakie jest preferowane rozwiązanie tego problemu, czy dotyczy to również CPython , czy dzieje się to w Pythonie 3 itp., itd.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 18:44:16
W Ubuntu 12.10 i terminalu GNOME nie występuje błąd, gdy program drukuje na stdout lub podłącza się do rury dla innych programów. Zarówno kodowanie plików, jak i kodowanie terminali to UTF-8 .
$ cat a.py
# -*- coding: utf-8 -*-
print "åäö"
$ python a.py
åäö
$ python a.py | tee out
åäö
Jakiego systemu operacyjnego i emulatora terminala używasz? Słyszałem, że niektórzy z moich kolegów mają podobne problemy podczas korzystania z iTerm 2 i OS X; iTerm 2 może być winowajcą.
Update: ta odpowiedź jest błędna - Zobacz komentarze szczegóły
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-04 15:38:58
Napotkałem ten problem w starszej aplikacji i trudno było określić, gdzie Wydrukowano to, co zostało wydrukowane. Pomogłem sobie z tym hackiem:
# encoding_utf8.py
import codecs
import builtins
def print_utf8(text, **kwargs):
print(str(text).encode('utf-8'), **kwargs)
def print_utf8(fn):
def print_fn(*args, **kwargs):
return fn(str(*args).encode('utf-8'), **kwargs)
return print_fn
builtins.print = print_utf8(print)
/ Align = "left" / test.py:
import encoding_utf8
string = 'Axwell Λ Ingrosso'
print(string)
Zauważ, że to zmienia wszystkie wywołania do drukowania, aby używać kodowania, więc konsola wydrukuje to:
$ python test.py
b'Axwell \xce\x9b Ingrosso'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 12:55:56