ฉันเห็นสคริปต์ py บางตัวซึ่งใช้ที่ด้านบนสุดของสคริปต์ ในกรณีใดควรใช้หรือไม่
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
ฉันเห็นสคริปต์ py บางตัวซึ่งใช้ที่ด้านบนสุดของสคริปต์ ในกรณีใดควรใช้หรือไม่
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
คำตอบ:
ตามเอกสารประกอบ: สิ่งนี้ช่วยให้คุณสามารถเปลี่ยนจาก ASCII เริ่มต้นเป็นการเข้ารหัสอื่น ๆ เช่น UTF-8 ซึ่ง Python runtime จะใช้เมื่อใดก็ตามที่มีการถอดรหัสบัฟเฟอร์สตริงเป็น Unicode
ฟังก์ชั่นนี้ใช้ได้เฉพาะในเวลาเริ่มต้น Python เมื่อ Python สแกนสภาพแวดล้อม มันจะต้องมีการเรียกในโมดูลทั้งระบบsitecustomize.py
,, หลังจากโมดูลนี้ได้รับการประเมินsetdefaultencoding()
ฟังก์ชั่นจะถูกลบออกจากsys
โมดูล
วิธีเดียวที่จะใช้งานได้จริงคือแฮ็กโหลดซ้ำที่นำคุณสมบัติกลับมา
นอกจากนี้การใช้งานsys.setdefaultencoding()
นั้นไม่ได้รับการสนับสนุนเสมอมาและมันกลายเป็นสิ่งที่ไม่มี op ใน py3k การเข้ารหัสของ py3k นั้นยากที่จะต่อสายเป็น "utf-8" และการเปลี่ยนมันทำให้เกิดข้อผิดพลาด
ฉันแนะนำตัวชี้บางอย่างสำหรับการอ่าน:
sys.stdout
เมื่อมีการNone
เข้ารหัสเช่นเมื่อเปลี่ยนเส้นทางการส่งออกของโปรแกรม Python)
sys.setdefaultencoding()
หมดกำลังใจเสมอ"
UTF-8
ไป LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
ให้UTF-8
แต่LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
ให้ANSI_X3.4-1968
(หรืออาจเป็นอย่างอื่น)
คำตอบคือไม่เคย ! (เว้นแต่คุณจะรู้ว่ากำลังทำอะไรอยู่)
9/10 เท่าของวิธีการแก้ปัญหาสามารถแก้ไขได้ด้วยความเข้าใจที่เหมาะสมของการเข้ารหัส / ถอดรหัส
1/10 คนมีสถานที่หรือสภาพแวดล้อมที่กำหนดไว้ไม่ถูกต้องและจำเป็นต้องตั้งค่า:
PYTHONIOENCODING="UTF-8"
ในสภาพแวดล้อมของพวกเขาเพื่อแก้ไขปัญหาการพิมพ์คอนโซล
(ขีดผ่านเพื่อหลีกเลี่ยงการใช้ซ้ำ) เปลี่ยนการเข้ารหัส / ถอดรหัสเริ่มต้นที่ใช้เมื่อใดก็ตามที่ Python 2.x จำเป็นต้องแปลง Unicode () เป็น str () (และในทางกลับกัน) และการเข้ารหัสไม่ได้รับ เช่น:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
ใน Python 2.x การเข้ารหัสเริ่มต้นถูกตั้งค่าเป็น ASCII และตัวอย่างข้างต้นจะล้มเหลวด้วย:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(คอนโซลของฉันถูกกำหนดค่าเป็น UTF-8 ดังนั้น"€" = '\xe2\x82\xac'
ข้อยกเว้นนี้\xe2
)
หรือ
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
จะอนุญาตให้ใช้งานได้สำหรับฉันแต่จะไม่จำเป็นสำหรับผู้ที่ไม่ได้ใช้ UTF-8 ค่าเริ่มต้นของ ASCII ทำให้มั่นใจได้ว่าสมมติฐานของการเข้ารหัสไม่ได้ถูกอบเข้าสู่โค้ดsys.setdefaultencoding("utf-8")
ยังมีผลข้างเคียงของการปรากฏเพื่อแก้ไขsys.setdefaultencoding("utf-8")
sys.stdout.encoding
ใช้เมื่อพิมพ์อักขระลงในคอนโซล Python ใช้ locale ของผู้ใช้ (Linux / OS X / Un * x) หรือ codepage (Windows) เพื่อตั้งค่านี้ บางครั้งสถานที่ของผู้ใช้เสียและเพียงแค่ต้องใช้PYTHONIOENCODING
ในการแก้ไขปัญหาการเข้ารหัสคอนโซล
ตัวอย่าง:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
ผู้คนพัฒนากับ Python 2.x เป็นเวลา 16 ปีในการทำความเข้าใจว่าการเข้ารหัสเริ่มต้นคือ ASCII UnicodeError
มีการเขียนวิธีการจัดการข้อยกเว้นเพื่อจัดการสตริงเป็น Conversion แบบ Unicode บนสตริงที่พบว่าไม่มี ASCII
จากhttps://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
ก่อนหน้าการตั้งค่าเริ่มต้นการเข้ารหัสรหัสนี้จะไม่สามารถถอดรหัส“ Å” ในการเข้ารหัส ascii จากนั้นจะป้อนตัวจัดการข้อยกเว้นเพื่อคาดเดาการเข้ารหัสและเปลี่ยนเป็นยูนิโค้ดอย่างถูกต้อง การพิมพ์: อังสตรอม (Å®) ดำเนินธุรกิจของคุณ เมื่อคุณตั้งค่าการเข้ารหัสเริ่มต้นเป็น utf-8 แล้วโค้ดจะพบว่า byte_string สามารถตีความได้ว่าเป็น utf-8 ดังนั้นมันจะทำให้ข้อมูลยุ่งเหยิงและส่งคืนสิ่งนี้แทน: Angstrom (Ů) ดำเนินธุรกิจของคุณ
การเปลี่ยนแปลงสิ่งที่ควรเป็นค่าคงที่จะมีผลอย่างมากต่อโมดูลที่คุณพึ่งพา ดีกว่าที่จะแก้ไขข้อมูลที่เข้าและออกจากรหัสของคุณ
ในขณะที่การตั้งค่าเริ่มต้นการเข้ารหัสเป็น UTF-8 ไม่ใช่รากสาเหตุในตัวอย่างต่อไปนี้มันแสดงให้เห็นว่าปัญหาถูกหลอกลวงและอย่างไรเมื่อการเข้ารหัสการป้อนข้อมูลเปลี่ยนแปลงรหัสจะแบ่งตัวในลักษณะที่ไม่เกรงกลัว: UnicodeDecodeError: 'utf8' ไม่ต้องถอดรหัส 0x80 ในตำแหน่ง 3131: ไบต์เริ่มต้นที่ไม่ถูกต้อง
sys.setdefaultencoding("utf-8")
ก็เป็นการดีที่จะทำให้โค้ดทำงานเหมือน Python 3 ตอนนี้เป็นปี 2017 แล้ว แม้ว่าคุณจะเขียนคำตอบกลับไปในปี 2558 ฉันคิดว่ามันจะดีกว่าถ้ามองไปข้างหน้าแทนที่จะถอยหลัง มันเป็นทางออกที่ง่ายที่สุดสำหรับฉันเมื่อฉันพบว่าโค้ดของฉันทำงานแตกต่างกันใน Python 2 ขึ้นอยู่กับว่าเอาต์พุตถูกเปลี่ยนเส้นทางหรือไม่ (เป็นปัญหาที่น่ารังเกียจสำหรับ Python 2) ไม่จำเป็นต้องพูดว่าฉันมีอยู่แล้ว# coding: utf-8
และฉันไม่ต้องการแก้ไขปัญหาใด ๆ สำหรับ Python 3 (จริง ๆ แล้วฉันต้องปิดบังการsetdefaultencoding
ตรวจสอบรุ่นที่ใช้)
sys.setdefaultencoding("utf-8")
ไม่ได้ทำให้รหัส Py 2.x ของคุณเข้ากันได้กับ Python 3 และไม่แก้ไขโมดูลภายนอกที่ถือว่าการเข้ารหัสเริ่มต้นคือ ASCII การทำให้โค้ดของคุณรองรับ Python 3 นั้นง่ายมากและไม่ต้องการแฮ็คที่น่ารังเกียจนี้ ตัวอย่างเช่นสาเหตุที่ทำให้เกิดปัญหาจริงลองดูประสบการณ์ของฉันกับ Amazon ที่ยุ่งกับสมมติฐานนี้: stackoverflow.com/questions/39465220//
PYTHONIOENCODING="UTF-8"
ช่วยให้สภาพแวดล้อม Python2.7 Django-1.11 ของฉันดีขึ้น ขอบคุณ
detect_encoding
แต่ฉันสามารถค้นหาสิ่งที่แพคเกจมี
detect_encoding
เป็นวิธีการที่สามารถตรวจจับการเข้ารหัสของสตริงตามเบาะแสภาษา
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
บนเชลล์ทำงานส่งไปยัง sdtout ไม่ได้ดังนั้นนั่นเป็นวิธีแก้ไขปัญหาเดียวเพื่อเขียนไปยัง stdout
ฉันใช้วิธีการอื่นซึ่งไม่ได้ทำงานหาก sys.stdout.encoding ไม่ได้กำหนดไว้หรือในคำอื่น ๆ จำเป็นต้องส่งออก PYTHONIOENCODING = UTF-8 ก่อนเพื่อเขียนไปยัง stdout
import sys
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)
ดังนั้นใช้ตัวอย่างเดียวกัน:
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
จะทำงาน
reload(sys)
ครั้งแรกที่อันตรายอยู่ใน
เมื่อคุณโหลดโมดูลใหม่คุณจะได้รับสำเนาของโมดูลสองชุดในรันไทม์ของคุณ โมดูลเก่าเป็นวัตถุ Python เหมือนทุกอย่างและยังมีชีวิตอยู่ตราบใดที่มีการอ้างอิงถึง ดังนั้นครึ่งหนึ่งของวัตถุจะถูกชี้ไปที่โมดูลเก่าและอีกครึ่งหนึ่งเป็นวัตถุใหม่ เมื่อคุณทำการเปลี่ยนแปลงบางอย่างคุณจะไม่เห็นการเปลี่ยนแปลงเกิดขึ้นเมื่อวัตถุสุ่มบางชิ้นไม่เห็นการเปลี่ยนแปลง:
(This is IPython shell)
In [1]: import sys
In [2]: sys.stdout
Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
In [3]: reload(sys)
<module 'sys' (built-in)>
In [4]: sys.stdout
Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
In [11]: import IPython.terminal
In [14]: IPython.terminal.interactiveshell.sys.stdout
Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
ตอนนี้sys.setdefaultencoding()
เหมาะสม
str<->unicode
ทุกสิ่งที่มันมีผลต่อการแปลงเป็นนัย ตอนนี้utf-8
การเข้ารหัส sanest บนดาวเคราะห์ (เข้ากันได้กับ ASCII และย้อนหลัง) การแปลงตอนนี้ "เพิ่งได้ผล" สิ่งที่อาจผิดไป?
อะไรก็ได้ และนั่นคืออันตราย
UnicodeError
การโยนสำหรับอินพุตที่ไม่ใช่ ASCII หรือการแปลงรหัสด้วยตัวจัดการข้อผิดพลาดซึ่งตอนนี้สร้างผลลัพธ์ที่ไม่คาดคิด และเนื่องจากรหัสทั้งหมดได้รับการทดสอบด้วยการตั้งค่าเริ่มต้นคุณจะอยู่ในอาณาเขต "ไม่ได้รับการสนับสนุน" ที่นี่อย่างเคร่งครัดและไม่มีผู้ใดให้การรับประกันแก่คุณเกี่ยวกับการทำงานของรหัสของพวกเขา