Po pierwsze: reload(sys)
a ustawienie jakiegoś losowego domyślnego kodowania tylko ze względu na potrzebę strumienia terminala wyjściowego jest złą praktyką. reload
często zmienia rzeczy w sys, które zostały wprowadzone w zależności od środowiska - np. strumienie sys.stdin / stdout, sys.excepthook itp.
Rozwiązanie problemu z kodowaniem na stdout
Najlepszym rozwiązaniem, jakie znam, aby rozwiązać problem z kodowaniem w przypadku print
ciągów znaków Unicode i poza-ascii str
(np. Z literałów) na sys.stdout jest: zająć się sys.stdout (obiekt podobny do pliku), który jest zdolny i opcjonalnie tolerancyjny w stosunku do potrzeb:
Kiedy sys.stdout.encoding
jest None
z jakiegoś powodu lub nie istnieje, błędnie fałszywe lub „mniejsze” niż to, do czego naprawdę jest zdolny terminal lub strumień standardowego strumienia, spróbuj podać poprawny .encoding
atrybut. W końcu zastępując sys.stdout & sys.stderr
go tłumaczącym obiektem podobnym do pliku.
Kiedy terminal / strumień nadal nie może zakodować wszystkich występujących znaków Unicode i nie chcesz z tego powodu łamać znaków, print
możesz wprowadzić zachowanie kodowania ze zamianą w tłumaczącym obiekcie podobnym do pliku.
Oto przykład:
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
Używanie zwykłych literałów łańcuchowych poza ascii w kodzie Python 2/2 + 3
Myślę, że jedynym dobrym powodem zmiany globalnego domyślnego kodowania (tylko na UTF-8) jest decyzja dotycząca kodu źródłowego aplikacji - a nie problemy z kodowaniem strumienia I / O: Do zapisywania literałów łańcuchowych poza ascii do kodu bez wymuszania aby zawsze używać u'string'
ucieczki stylu Unicode. Można to zrobić dość konsekwentnie (pomimo tego, co mówi artykuł anonbadger ), dbając o podstawę kodu źródłowego Python 2 lub Python 2 + 3, który konsekwentnie używa zwykłych literałów ciągów ascii lub UTF-8 - o ile te ciągi potencjalnie podlegają wyciszeniu Konwersja Unicode i przechodzenie między modułami lub potencjalnie przejście do standardowego wyjścia. W tym celu preferuj „# encoding: utf-8
"lub ascii (brak deklaracji). Zmień lub usuń biblioteki, które nadal polegają w bardzo głupi sposób na błędach domyślnego kodowania ascii poza chr # 127 (co jest dziś rzadkością).
I zrób to na starcie aplikacji (i / lub przez sitecustomize.py) jako dodatek do SmartStdout
powyższego schematu - bez użycia reload(sys)
:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
W ten sposób literały łańcuchowe i większość operacji (z wyjątkiem iteracji znaków) działają wygodnie, bez myślenia o konwersji Unicode, tak jakby istniał tylko Python3. Oczywiście we / wy pliku zawsze trzeba uważać na kodowanie - tak jak w Pythonie3.
Uwaga: łańcuchy SmartStdout
zwykłe są następnie niejawnie konwertowane z utf-8 do Unicode, zanim zostaną przekonwertowane na kodowanie strumienia wyjściowego.