Pertama: reload(sys)
dan menyetel beberapa pengkodean default acak hanya terkait kebutuhan aliran terminal keluaran adalah praktik yang buruk. reload
sering mengubah hal-hal dalam sys yang telah diterapkan tergantung pada lingkungan - misalnya aliran sys.stdin / stdout, sys.excepthook, dll.
Memecahkan masalah encode di stdout
Solusi terbaik yang saya tahu untuk memecahkan masalah encode dari print
string unicode dan di luar-ascii str
(misalnya dari literals) di sys.stdout adalah: menjaga sys.stdout (objek seperti file) yang mampu dan secara opsional toleran terhadap kebutuhan:
Ketika sys.stdout.encoding
ini None
untuk beberapa alasan, atau non-ada, atau keliru palsu atau "kurang" dari apa yang stdout terminal atau streaming benar-benar mampu, kemudian mencoba untuk memberikan yang benar .encoding
atribut. Akhirnya dengan mengganti sys.stdout & sys.stderr
dengan objek seperti file terjemahan.
Ketika terminal / stream masih tidak dapat menyandikan semua karakter unicode yang terjadi, dan ketika Anda tidak ingin merusaknya print
hanya karena itu, Anda dapat memperkenalkan perilaku encode-with-replace dalam menerjemahkan objek seperti file.
Berikut contohnya:
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()
Menggunakan literal string biasa di luar ascii dengan kode Python 2/2 + 3
Satu-satunya alasan yang baik untuk mengubah pengkodean default global (ke UTF-8 saja) menurut saya adalah mengenai keputusan kode sumber aplikasi - dan bukan karena masalah pengkodean aliran I / O: Untuk menulis literal string ascii ke dalam kode tanpa dipaksa untuk selalu menggunakan u'string'
pelolosan unicode gaya. Hal ini dapat dilakukan secara agak konsisten (terlepas dari apa yang anonbadger artikel ) dengan menjaga basis kode sumber Python 2 atau Python 2 + 3 yang menggunakan literal string biasa ascii atau UTF-8 secara konsisten - sejauh string tersebut berpotensi menjalani silent unicode dan berpindah antar modul atau berpotensi pergi ke stdout. Untuk itu, pilih "# encoding: utf-8
"atau ascii (tanpa deklarasi). Ubah atau jatuhkan pustaka yang masih mengandalkan dengan cara yang sangat bodoh secara fatal pada kesalahan pengkodean default ascii di luar chr # 127 (yang jarang terjadi saat ini).
Dan lakukan seperti ini pada permulaan aplikasi (dan / atau melalui sitecustomize.py) selain SmartStdout
skema di atas - tanpa menggunakan 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
Dengan cara ini string literal dan sebagian besar operasi (kecuali iterasi karakter) bekerja dengan nyaman tanpa memikirkan konversi unicode seolah-olah hanya akan ada Python3. File I / O tentu saja selalu membutuhkan perhatian khusus terkait pengkodean - seperti pada Python3.
Catatan: string dataran kemudian secara implisit diubah dari utf-8 menjadi unicode SmartStdout
sebelum diubah menjadi enconding aliran keluaran.