ครั้งแรก: reload(sys)
และการตั้งค่าการเข้ารหัสเริ่มต้นแบบสุ่มเพียงแค่เกี่ยวกับความต้องการของกระแสข้อมูลเทอร์มินัลเอาท์พุทคือการปฏิบัติที่ไม่ดี reload
มักจะเปลี่ยนสิ่งต่าง ๆ ใน sys ซึ่งวางไว้ในสภาพแวดล้อม - เช่น sys.stdin / stdout ลำธาร sys.excepthook ฯลฯ
การแก้ปัญหาการเข้ารหัสใน stdout
ทางออกที่ดีที่สุดที่ฉันรู้ในการแก้ปัญหาการเข้ารหัสของprint
'ing unicode strings และ Beyond-ascii str
' s (เช่นจากตัวอักษร) ใน sys.stdout คือ: การดูแล sys.stdout (วัตถุคล้ายไฟล์) ซึ่งมีความสามารถและ เผื่อเลือกเกี่ยวกับความต้องการ:
เมื่อsys.stdout.encoding
มีNone
เหตุผลบางอย่างหรือไม่ใช่ที่มีอยู่หรือเท็จผิดหรือ "น้อย" กว่าสิ่งที่เทอร์มินัล stdout หรือสตรีมมีความสามารถจริง ๆ แล้วลองจัดหา.encoding
แอตทริบิวต์ที่ถูกต้อง ในที่สุดโดยการแทนที่sys.stdout & sys.stderr
โดยวัตถุเหมือนไฟล์แปล
เมื่อเทอร์มินัล / สตรีมยังไม่สามารถเข้ารหัสตัวอักษรแบบ unicode ทั้งหมดที่เกิดขึ้นและเมื่อคุณไม่ต้องการทำลายprint
เพราะสิ่งนั้นคุณสามารถนำเสนอพฤติกรรมแบบเข้ารหัสพร้อมแทนที่ในวัตถุคล้ายไฟล์แปล
นี่คือตัวอย่าง:
#!/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()
การใช้ตัวอักษรสตริงแบบธรรมดาเกิน ASCII ในรหัส Python 2/2 + 3
เหตุผลเดียวที่ดีในการเปลี่ยนการเข้ารหัสเริ่มต้นทั่วโลก (เป็น UTF-8 เท่านั้น) ฉันคิดว่าเกี่ยวข้องกับการตัดสินใจซอร์สโค้ดของแอปพลิเคชัน- และไม่ใช่เพราะปัญหาการเข้ารหัส I / O สตรีม: สำหรับการเขียนตัวอักษรสตริงที่เกิน ascii ลงในรหัส เพื่อใช้การu'string'
หลบหนีแบบ Unicode สไตล์เสมอ สิ่งนี้สามารถทำได้ค่อนข้างสม่ำเสมอ (แม้จะมีบทความของanonbadgerกล่าวไว้) โดยการดูแลพื้นฐานซอร์สโค้ด Python 2 หรือ Python 2 + 3 ซึ่งใช้ตัวอักษรสตริงธรรมดา ASCII หรือ UTF-8 อย่างสม่ำเสมอ - ตราบใดที่สตริงเหล่านั้นอาจถูกปิดเสียง แปลง Unicode และย้ายไปมาระหว่างโมดูลหรืออาจไปที่ stdout สำหรับที่ต้องการ "# encoding: utf-8
"หรือ ascii (ไม่มีการประกาศ) เปลี่ยนหรือวางไลบรารี่ซึ่งยังคงพึ่งพาวิธีที่โง่มากในการเข้ารหัสข้อผิดพลาดเริ่มต้นของ ASCII เกิน chr # 127 (ซึ่งหาได้ยากในปัจจุบัน)
และทำเช่นนี้เมื่อเริ่มต้นแอปพลิเคชัน (และ / หรือผ่าน sitecustomize.py) นอกเหนือจากSmartStdout
รูปแบบข้างต้น - โดยไม่ต้องใช้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
วิธีนี้จะใช้ตัวอักษรสตริงและการดำเนินการส่วนใหญ่ (ยกเว้นการวนซ้ำตัวอักษร) ทำงานได้อย่างสะดวกสบายโดยไม่ต้องนึกถึงการแปลง Unicode ราวกับว่าจะมี Python3 เท่านั้น แน่นอนว่าไฟล์ I / O นั้นจะต้องมีความระมัดระวังเป็นพิเศษเกี่ยวกับการเข้ารหัสเนื่องจากมันอยู่ใน Python3
หมายเหตุ: สตริงของ plains นั้นจะถูกแปลงแบบไม่แน่นอนจาก utf-8 เป็น unicode SmartStdout
ก่อนที่จะถูกแปลงเป็นเอาต์พุตสตรีมที่เข้ารหัส