PEP 686 - ตั้งค่าโหมด UTF-8 เป็นค่าเริ่มต้นตั้งแต่ Python 3.15
- UTF-8 กำลังกลายเป็นมาตรฐานการเข้ารหัสข้อความโดยพฤตินัย
- การเข้ารหัสเริ่มต้นของไฟล์ซอร์ส Python คือ UTF-8
- JSON, TOML, YAML ใช้ UTF-8
- โปรแกรมแก้ไขข้อความส่วนใหญ่ เช่น Visual Studio Code, Windows Notepad ใช้ UTF-8 เป็นค่าเริ่มต้น
- เว็บไซต์ส่วนใหญ่และข้อมูลข้อความบนอินเทอร์เน็ตใช้ UTF-8
- ภาษาโปรแกรมยอดนิยมอื่น ๆ จำนวนมาก เช่น Node.js, Go, Rust, Java ก็ใช้ UTF-8 เป็นค่าเริ่มต้นเช่นกัน
- การเปลี่ยนการเข้ารหัสเริ่มต้นเป็น UTF-8 จะทำให้ Python ทำงานร่วมกับภาษาอื่นได้ง่ายขึ้น
- นักพัฒนา Python จำนวนมากที่ใช้ Unix มักลืมไปว่าการเข้ารหัสเริ่มต้นแตกต่างกันไปตามแพลตฟอร์ม
- เมื่อต้องอ่านไฟล์ข้อความที่เข้ารหัสด้วย UTF-8 (เช่น JSON, TOML, Markdown, ไฟล์ซอร์ส Python) มักไม่ระบุ
encoding="utf-8"
- การเข้ารหัสเริ่มต้นที่ไม่สอดคล้องกันทำให้เกิดบั๊กจำนวนมาก
การเปลี่ยนแปลงสำคัญใน PEP 686
- ตั้งแต่ Python 3.15 เป็นต้นไป โหมด UTF-8 จะถูกเปิดใช้งานเป็นค่าเริ่มต้น
- ผู้ใช้ยังคงสามารถปิดโหมด UTF-8 ได้ด้วยการตั้งค่า
PYTHONUTF8=0 หรือ -X utf8=0
- เพิ่ม
locale.getencoding()
- เป็น API สำหรับรับการเข้ารหัสตาม locale โดยไม่ขึ้นกับโหมด UTF-8
- หากระบุออปชัน
warn_default_encoding แล้ว locale.getpreferredencoding() จะส่ง EncodingWarning เช่นเดียวกับ open() (ดู PEP 597)
- ปรับแก้ออปชัน
encoding="locale"
TextIOWrapper ควรใช้การเข้ารหัสตาม locale แม้อยู่ในโหมด UTF-8 หากระบุ encoding="locale"
ความเข้ากันได้ย้อนหลัง
- ระบบ Unix ส่วนใหญ่ใช้ locale แบบ UTF-8 และ Python จะเปิดโหมด UTF-8 เมื่อ locale เป็น C หรือ POSIX ดังนั้นการเปลี่ยนแปลงนี้จึงส่งผลหลักกับผู้ใช้ Windows
- หากโปรแกรม Python พึ่งพาการเข้ารหัสเริ่มต้น การเปลี่ยนแปลงนี้อาจทำให้เกิด
UnicodeError, ข้อความเพี้ยน หรือข้อมูลเสียหายแบบเงียบ ๆ ได้
- แนวทางในการแก้ปัญหาความเข้ากันได้ย้อนหลัง:
- ปิดโหมด UTF-8
- ใช้
EncodingWarning (PEP 597) เพื่อค้นหาทุกจุดที่ได้รับผลกระทบจากโหมด UTF-8
- หากละเว้นออปชัน
encoding ให้พิจารณาใช้ encoding="utf-8" หรือ encoding="locale"
- หากมีการใช้
locale.getpreferredencoding() ให้พิจารณาใช้ "utf-8" หรือ locale.getencoding()
- ทดสอบแอปพลิเคชันด้วยโหมด UTF-8
ความเห็นของ GN⁺
- PEP นี้มีเป้าหมายเพื่อทำให้การเข้ารหัสเริ่มต้นของ Python เป็น UTF-8 แบบ统一 เพื่อเพิ่มความสามารถในการทำงานร่วมกับภาษาและระบบอื่น ๆ ซึ่งจะช่วยให้ Python ถูกใช้งานได้ราบรื่นยิ่งขึ้นในสภาพแวดล้อมการพัฒนาระดับโลก
- อย่างไรก็ตาม การเปลี่ยนแปลงนี้อาจส่งผลต่อความเข้ากันได้ย้อนหลังของโปรแกรม Python ที่มีอยู่เดิม โดยเฉพาะโปรแกรมที่ทำงานในสภาพแวดล้อม Windows ซึ่งต้องใช้ความระมัดระวัง
- นักพัฒนาควรใช้
EncodingWarning เพื่อระบุส่วนที่ได้รับผลกระทบ และรับมือด้วยวิธีต่าง ๆ เช่น การระบุออปชัน encoding อย่างชัดเจน
- ในระยะยาว คาดว่าการเปลี่ยนแปลงนี้จะส่งผลเชิงบวกต่อระบบนิเวศของ Python แต่ในระยะสั้น บางโปรเจกต์อาจมีต้นทุนในการย้ายระบบ
- นักพัฒนาควรคำนึงถึงการเปลี่ยนแปลงนี้เมื่อวางแผนอัปเกรดไปยัง Python 3.15 และหากจำเป็นก็ควรดำเนินมาตรการที่เหมาะสมเพื่อรองรับความเข้ากันได้ย้อนหลัง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
init.dโดยสคริปต์รัน Java ที่ทำงานด้วยสิทธิ์ root ใช้การเข้ารหัสต่างจากผู้ใช้ทั่วไปจนเกิดปัญหาPython 2 ไม่ยึดติดกับ charset จึงมักทำงานได้เสมอ แต่การปรับปรุงของ Python 3 นั้นเกินกว่าจะเรียกว่าแค่การปรับปรุง
วิธีแยกสคริปต์ Python 3 ออกจากสคริปต์ Python 2:
"utf-8"ก็เป็น Python 3C.UTF-8ก็เป็น Python 3การเปลี่ยนแปลงครั้งนี้น่ายินดีต้อนรับ และดูเหมือนจะทำให้ Python 3 "ดีขึ้น"
นึกว่ามันเป็นค่าเริ่มต้นมาตั้งแต่ Python 3 แล้ว
ไม่เคยรู้ว่า Java ย้ายจาก UTF-16 มาเป็น UTF-8 แล้ว
ไม่แน่ใจว่าการเข้ารหัสภายในของ CPython เป็น UTF-8 หรือไม่
สตริงของ Python สามารถทำ indexing ได้ แต่การเข้าถึงแบบสุ่มเกิดขึ้นไม่บ่อย จึงน่าจะดีกว่าถ้าทำดัชนีแบบหน่วงเวลาเมื่อจำเป็น
ถ้าแค่เลื่อนไปข้างหน้าหรือถอยหลังทีละตำแหน่งก็ไม่จำเป็นต้องมีดัชนี
ดังนั้นจึงดูเหมือนว่าน่าจะใช้ตัวแทนภายในแบบ UTF-8 ได้
ทำไมไม่ใช้
utf-8-sig? มันมีประโยชน์เพราะจัดการ BOM แบบเลือกได้พูดถึง UTF-8 แล้ว Linux framebuffer ควรมีการรองรับ UTF-8 ที่เหมาะสมมาตั้งนานแล้ว
GNU Hurd มี 'terminal console' ที่ดีกว่าและรองรับ UTF-8 มาตั้งแต่ราวปี 2007
นี่ปี 2024 แล้วเพิ่งมีการเปลี่ยนแปลงแบบนี้
เป็นการเปลี่ยนแปลงที่ดี ตอนนี้ก็เหลือแค่ JS ที่ต้องเปลี่ยนมาใช้ UTF-8 แต่การปรับปรุงทำได้ยากเพราะต้องเข้ากันได้กับโค้ดที่เขียนไว้ตั้งแต่ปี 1995