Sumber utama masalah yang saya alami saat bekerja dengan string unicode adalah saat Anda mencampur string yang dikodekan utf-8 dengan yang unicode.
Misalnya, perhatikan skrip berikut.
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
Output dari menjalankan python one.py
adalah:
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)
Dalam contoh ini, two.name
adalah string yang dienkode utf-8 (bukan unicode) karena tidak diimpor unicode_literals
, dan one.name
merupakan string unicode. Saat Anda mencampur keduanya, python mencoba mendekode string yang dikodekan (dengan asumsi itu ascii) dan mengubahnya menjadi unicode dan gagal. Ini akan berhasil jika Anda melakukannya print name + two.name.decode('utf-8')
.
Hal yang sama dapat terjadi jika Anda menyandikan string dan mencoba mencampurnya nanti. Misalnya, ini berfungsi:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Keluaran:
DEBUG: <html><body>helló wörld</body></html>
Tetapi setelah menambahkan import unicode_literals
itu TIDAK:
# 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
Keluaran:
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)
Gagal karena 'DEBUG: %s'
merupakan string unicode dan oleh karena itu python mencoba memecahkan kode html
. Beberapa cara untuk memperbaiki hasil cetak adalah melakukan print str('DEBUG: %s') % html
atau print 'DEBUG: %s' % html.decode('utf-8')
.
Saya harap ini membantu Anda memahami potensi gotcha saat menggunakan string unicode.
decode()
solusi daripada solusistr()
atauencode()
: semakin sering Anda menggunakan objek Unicode, semakin jelas kodenya, karena yang Anda inginkan adalah memanipulasi string karakter, bukan array byte dengan pengkodean yang tersirat secara eksternal.when you mix utf-8 encoded strings with unicode ones
UTF-8 dan Unicode bukan merupakan 2 pengkodean yang berbeda; Unicode adalah standar dan UTF-8 adalah salah satu pengkodean yang didefinisikannya.str
, yang terakhir adalah tipeunicode
. Karena objek yang berbeda, masalah dapat muncul jika Anda mencoba untuk menjumlahkan / menggabungkan / menginterpolasi merekapython>=2.6
ataupython==2.6
?Juga di 2.6 (sebelum python 2.6.5 RC1 +) literal unicode tidak cocok dengan argumen kata kunci ( issue4978 ):
Kode berikut ini misalnya berfungsi tanpa unicode_literals, tetapi gagal dengan TypeError:
keywords must be string
jika unicode_literals digunakan.sumber
Saya menemukan bahwa jika Anda menambahkan
unicode_literals
direktif, Anda juga harus menambahkan sesuatu seperti:ke baris pertama atau kedua file .py Anda. Jika tidak, garis seperti:
mengakibatkan kesalahan seperti:
sumber
# -*- coding: utf-8
adalah pernyataan yang hampir wajib terlepas dari apakah Anda menggunakanunicode_literals
atau tidak-*-
diperlukan; jika Anda memilih cara yang kompatibel dengan emacs, saya pikir Anda akan membutuhkannya-*- encoding: utf-8 -*-
(lihat juga-*-
di bagian akhir). Yang Anda butuhkan hanyalahcoding: utf-8
(atau bahkan=
bukan:
).from __future__ import unicode_literals
.# -*- coding: utf-8 -*-
"pengkodean" (bukan "pengkodean" atau "pengkodean file" atau yang lainnya - Python hanya mencari "pengkodean" terlepas dari awalan apapun).Juga pertimbangkan bahwa
unicode_literal
akan mempengaruhieval()
tetapi tidakrepr()
(perilaku asimetris yang imho adalah bug), yaitueval(repr(b'\xa4'))
tidak akan sama denganb'\xa4'
(seperti pada Python 3).Idealnya, kode berikut akan menjadi invarian, yang seharusnya selalu berfungsi, untuk semua kombinasi
unicode_literals
dan penggunaan Python {2.7, 3.x}:Pernyataan kedua berhasil, karena
repr('\xa4')
dievaluasi denganu'\xa4'
Python 2.7.sumber
repr
untuk meregenerasi sebuah objek. Therepr
dokumentasi jelas menyatakan bahwa ini bukan keharusan. Menurut pendapat saya, ini mengacurepr
pada sesuatu yang hanya berguna untuk debugging.Masih ada lagi.
Ada pustaka dan bawaan yang mengharapkan string yang tidak mentolerir unicode.
Dua contoh:
builtin:
(sedikit esotik) tidak berfungsi dengan unicode_literals: type () mengharapkan string.
Perpustakaan:
tidak berfungsi: pustaka wx pubsub mengharapkan tipe pesan string.
Yang pertama bersifat esoterik dan mudah diperbaiki
tetapi yang terakhir ini menghancurkan jika kode Anda penuh dengan panggilan ke pub.sendMessage () (yang milik saya).
Sial, eh?!?
sumber
class Meta:
seharusnyab'field_name'
Klik akan memunculkan pengecualian unicode di semua tempat jika ada modul yang
from __future__ import unicode_literals
diimpor di tempat Anda menggunakanclick.echo
. Ini mimpi buruk…sumber