สาเหตุหลักของปัญหาที่ฉันเคยใช้กับสตริง Unicode คือเมื่อคุณผสมสตริงที่เข้ารหัส utf-8 กับสตริงที่มียูนิโคด
ตัวอย่างเช่นพิจารณาสคริปต์ต่อไปนี้
two.py
# encoding: utf-8
name = 'helló wörld from two'
one.py
# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name
ผลลัพธ์ของการทำงานpython one.py
คือ:
Traceback (most recent call last):
File "one.py", line 5, in <module>
print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
ในตัวอย่างtwo.name
นี้เป็นสตริงที่เข้ารหัส utf-8 (ไม่ใช่ Unicode) เนื่องจากไม่ได้นำเข้าunicode_literals
และone.name
เป็นสตริง Unicode เมื่อคุณผสมทั้งสองอย่าง python จะพยายามถอดรหัสสตริงที่เข้ารหัส (สมมติว่าเป็น ascii) และแปลงเป็น Unicode และล้มเหลว print name + two.name.decode('utf-8')
มันจะทำงานถ้าคุณไม่ได้ทำ
สิ่งเดียวกันนี้สามารถเกิดขึ้นได้หากคุณเข้ารหัสสตริงและพยายามผสมในภายหลัง ตัวอย่างเช่นการทำงานนี้:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
เอาท์พุต:
DEBUG: <html><body>helló wörld</body></html>
แต่หลังจากเพิ่มimport unicode_literals
มันจะไม่:
# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
เอาท์พุต:
Traceback (most recent call last):
File "test.py", line 6, in <module>
print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)
มันล้มเหลวเนื่องจาก'DEBUG: %s'
เป็นสายอักขระ Unicode html
และดังนั้นจึงพยายามที่จะถอดรหัสหลาม สองวิธีในการแก้ไขการพิมพ์คือทำprint str('DEBUG: %s') % html
หรือprint 'DEBUG: %s' % html.decode('utf-8')
หรือ
ฉันหวังว่านี่จะช่วยให้คุณเข้าใจ gotchas ที่อาจเกิดขึ้นเมื่อใช้สตริง Unicode
decode()
โซลูชันแทนstr()
หรือencode()
โซลูชัน: ยิ่งคุณใช้อ็อบเจ็กต์ Unicode บ่อยเท่าไหร่โค้ดก็ยิ่งชัดเจนขึ้นเท่านั้นเนื่องจากสิ่งที่คุณต้องการคือการจัดการสตริงของอักขระไม่ใช่อาร์เรย์ของไบต์ที่มีการเข้ารหัสโดยนัยจากภายนอก