unicode_escape
tidak berfungsi secara umum
Ternyata solusi string_escape
atau unicode_escape
tidak berfungsi secara umum - terutama, tidak berfungsi dengan adanya Unicode yang sebenarnya.
Jika Anda dapat yakin bahwa setiap karakter non-ASCII akan di-escape (dan ingat, apa pun di luar 128 karakter pertama adalah non-ASCII), unicode_escape
akan melakukan hal yang benar untuk Anda. Tetapi jika sudah ada karakter non-ASCII literal dalam string Anda, semuanya akan salah.
unicode_escape
pada dasarnya dirancang untuk mengubah byte menjadi teks Unicode. Tetapi di banyak tempat - misalnya, kode sumber Python - data sumber sudah berupa teks Unicode.
Satu-satunya cara ini dapat bekerja dengan benar adalah jika Anda mengenkode teks menjadi byte terlebih dahulu. UTF-8 adalah pengkodean yang masuk akal untuk semua teks, sehingga seharusnya berfungsi, bukan?
Contoh berikut ada di Python 3, sehingga literal string lebih bersih, tetapi masalah yang sama ada dengan manifestasi yang sedikit berbeda pada Python 2 dan 3.
>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve test
Itu salah.
Cara baru yang disarankan untuk menggunakan codec yang mendekode teks menjadi teks adalah dengan memanggil codecs.decode
secara langsung. Apakah itu membantu?
>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve test
Tidak semuanya. (Juga, di atas adalah UnicodeError pada Python 2.)
The unicode_escape
codec, meskipun namanya, ternyata menganggap bahwa semua byte non-ASCII berada di Latin-1 (ISO-8859-1) encoding. Jadi, Anda harus melakukannya seperti ini:
>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve test
Tapi itu mengerikan. Ini membatasi Anda pada 256 karakter Latin-1, seolah Unicode belum pernah ditemukan sama sekali!
>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)
Menambahkan ekspresi reguler untuk menyelesaikan masalah
(Anehnya, sekarang kami tidak memiliki dua masalah.)
Yang perlu kita lakukan hanyalah menerapkan unicode_escape
decoder ke hal-hal yang kita yakini teks ASCII. Secara khusus, kami dapat memastikan hanya untuk menerapkannya ke urutan escape Python yang valid, yang dijamin menjadi teks ASCII.
Rencananya, kita akan menemukan escape sequence menggunakan regular expression, dan menggunakan fungsi sebagai argumen re.sub
untuk menggantinya dengan nilai unescaped.
import re
import codecs
ESCAPE_SEQUENCE_RE = re.compile(r'''
( \\U........ # 8-digit hex escapes
| \\u.... # 4-digit hex escapes
| \\x.. # 2-digit hex escapes
| \\[0-7]{1,3} # Octal escapes
| \\N\{[^}]+\} # Unicode characters by name
| \\[\\'"abfnrtv] # Single-character escapes
)''', re.UNICODE | re.VERBOSE)
def decode_escapes(s):
def decode_match(match):
return codecs.decode(match.group(0), 'unicode-escape')
return ESCAPE_SEQUENCE_RE.sub(decode_match, s)
Dan dengan itu:
>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő Rubik
'spam'+"eggs"+'''some'''+"""more"""
diproses?