UnicodeDecodeError, byte kelanjutan tidak valid


257

Mengapa item di bawah ini gagal? dan mengapa itu berhasil dengan codec "latin-1"?

o = "a test of \xe9 char" #I want this to remain a string as this is what I am receiving
v = o.decode("utf-8")

menghasilkan:

 Traceback (most recent call last):  
 File "<stdin>", line 1, in <module>  
 File "C:\Python27\lib\encodings\utf_8.py",
 line 16, in decode
     return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError:
 'utf8' codec can't decode byte 0xe9 in position 10: invalid continuation byte

Jawaban:


247

Dalam biner, 0xE9 terlihat seperti 1110 1001. Jika Anda membaca tentang UTF-8 di Wikipedia , Anda akan melihat bahwa byte tersebut harus diikuti oleh dua formulir 10xx xxxx. Jadi, misalnya:

>>> b'\xe9\x80\x80'.decode('utf-8')
u'\u9000'

Tapi itu hanya penyebab mekanis pengecualiannya. Dalam hal ini, Anda memiliki string yang hampir pasti dikodekan dalam latin 1. Anda dapat melihat bagaimana UTF-8 dan latin 1 terlihat berbeda:

>>> u'\xe9'.encode('utf-8')
b'\xc3\xa9'
>>> u'\xe9'.encode('latin-1')
b'\xe9'

(Catatan, saya menggunakan campuran representasi Python 2 dan 3 di sini. Input ini valid dalam versi Python apa pun, tetapi juru bahasa Python Anda tidak mungkin benar-benar menunjukkan string unicode dan byte dengan cara ini.)


2
Terima kasih (dan kepada yang lain yang menjawab), saya berada di bawah kepercayaan yang keliru bahwa karakter hingga 255 akan langsung bertobat.
RuiDC

Saya mendapatkan UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)kesalahan dalam menggunakan.encode(latin-1)
Shiva

234

Saya memiliki kesalahan yang sama ketika saya mencoba membuka file csv dengan metode read_csv panda.

Solusinya adalah mengubah encoding ke 'latin-1':

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1')

1
Apakah ini benar-benar menyelesaikan masalah? Bukankah itu pada dasarnya hanya memberitahu panda untuk mengabaikan byte dengan menurunkan ke gaya pengkodean yang kurang kompleks?
Yu Chen

61

Itu tidak valid UTF-8. Karakter itu adalah karakter e-akut dalam ISO-Latin1, itulah sebabnya ia berhasil dengan kode itu.

Jika Anda tidak tahu set kode tempat Anda menerima string, berarti Anda sedikit kesulitan. Akan lebih baik jika satu kode tunggal (mudah-mudahan UTF-8) akan dipilih untuk protokol / aplikasi Anda dan kemudian Anda hanya akan menolak yang tidak diterjemahkan.

Jika Anda tidak bisa melakukan itu, Anda perlu heuristik.


2
Dan untuk heuristik, lihat perpustakaan chardet.
mlissner

44

Karena UTF-8 adalah multibyte dan tidak ada karakter yang sesuai dengan kombinasi Anda \xe9 ditambah ruang berikut.

Mengapa harus berhasil dalam kedua utf-8 dan latin-1?

Di sini bagaimana kalimat yang sama harus di utf-8:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'

Latin-1 adalah keluarga pengodean byte tunggal sehingga semua yang ada di dalamnya harus didefinisikan dalam UTF-8. Tetapi mengapa kadang-kadang menang Latin-1?
Reihan_amn

11

Jika kesalahan ini muncul saat memanipulasi file yang baru saja dibuka, periksa untuk melihat apakah Anda membukanya dalam 'rb'mode


2
Berkat jawaban ini, dapat menghindari kesalahan, UnicodeDecodeError: 'utf-8' codec tidak dapat mendekode byte 0xd7 di posisi 2024079: byte kelanjutan tidak valid oleh soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Philip

6

Ini juga terjadi pada saya, ketika saya sedang membaca teks yang mengandung bahasa Ibrani dari sebuah .txtfile.

Saya mengklik: file -> save asdan saya menyimpan file ini sebagai UTF-8penyandian


5

kode utf-8 biasanya muncul ketika kisaran nilai numerik melebihi 0 hingga 127.

alasan untuk mengajukan pengecualian ini adalah:

1) Jika titik kode <128, setiap byte sama dengan nilai titik kode. 2) Jika titik kode 128 atau lebih besar, string Unicode tidak dapat direpresentasikan dalam pengkodean ini. (Python memunculkan pengecualian UnicodeEncodeError dalam kasus ini.)

Untuk mengatasi ini kami memiliki satu set pengkodean, yang paling banyak digunakan adalah "Latin-1, juga dikenal sebagai ISO-8859-1"

Jadi ISO-8859-1 Unicode poin 0-255 identik dengan nilai Latin-1, jadi konversi ke pengkodean ini hanya memerlukan konversi titik kode ke nilai byte; jika titik kode lebih besar dari 255 ditemui, string tidak dapat dikodekan ke dalam Latin-1

ketika pengecualian ini terjadi ketika Anda mencoba memuat kumpulan data, coba gunakan format ini

df=pd.read_csv("top50.csv",encoding='ISO-8859-1')

Tambahkan teknik pengkodean di akhir sintaks yang kemudian menerima untuk memuat kumpulan data.


Hai dan selamat datang di SO! Harap edit jawaban Anda untuk memastikannya meningkatkan jawaban lain yang sudah ada dalam pertanyaan ini.
hongsy


-1

Dalam hal ini, saya mencoba menjalankan .py yang mengaktifkan path / file.sql.

Solusi saya adalah memodifikasi kodifikasi file.sql menjadi "UTF-8 tanpa BOM" dan berhasil!

Anda dapat melakukannya dengan Notepad ++.

saya akan meninggalkan bagian dari kode saya.

/ Kode /

con = psycopg2.connect (host = sys.argv [1], port = sys.argv [2], dbname = sys.argv [3], pengguna = sys.argv [4], kata sandi = sys.argv [5] )

cursor = con.cursor () sqlfile = open (path, 'r')

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.