UnicodeDecodeError, byte tiếp tục không hợp lệ


257

Tại sao các mục dưới đây không thành công? và tại sao nó thành công với 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")

kết quả trong:

 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

Câu trả lời:


247

Trong nhị phân, 0xE9 trông như thế 1110 1001. Nếu bạn đọc về UTF-8 trên Wikipedia , bạn sẽ thấy rằng một byte như vậy phải được theo sau bởi hai trong số các hình thức 10xx xxxx. Ví dụ:

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

Nhưng đó chỉ là nguyên nhân cơ học của ngoại lệ. Trong trường hợp này, bạn có một chuỗi gần như chắc chắn được mã hóa bằng tiếng Latin 1. Bạn có thể thấy UTF-8 và latin 1 trông khác nhau như thế nào:

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

(Lưu ý, tôi đang sử dụng kết hợp biểu diễn Python 2 và 3 ở đây. Đầu vào hợp lệ trong bất kỳ phiên bản Python nào, nhưng trình thông dịch Python của bạn không thực sự hiển thị cả chuỗi unicode và byte theo cách này.)


2
Cảm ơn (và cho người khác đã trả lời), tôi đã có niềm tin nhầm lẫn rằng ký tự lên đến 255 sẽ trực tiếp chuyển đổi.
RuiDC

Tôi gặp UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)lỗi khi sử dụng.encode(latin-1)
Shiva

234

Tôi đã gặp lỗi tương tự khi tôi cố mở tệp csv bằng phương thức pandas read_csv.

Giải pháp là thay đổi mã hóa thành 'latin-1':

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

1
Điều này thực sự giải quyết vấn đề mặc dù? Không phải về cơ bản nó chỉ bảo gấu trúc bỏ qua byte bằng cách hạ cấp xuống một kiểu mã hóa ít phức tạp hơn sao?
Yu Chen

61

Đó là UTF-8 không hợp lệ. Nhân vật đó là nhân vật cấp tính điện tử trong ISO-Latin1, đó là lý do tại sao nó thành công với bộ mã đó.

Nếu bạn không biết bộ mã bạn đang nhận chuỗi, bạn sẽ gặp một chút rắc rối. Sẽ là tốt nhất nếu một bộ mã duy nhất (hy vọng UTF-8) sẽ được chọn cho giao thức / ứng dụng của bạn và sau đó bạn sẽ từ chối những bộ không giải mã được.

Nếu bạn không thể làm điều đó, bạn sẽ cần heuristic.


2
Và đối với heuristic, xem thư viện chardet.
mlissner

44

Bởi vì UTF-8 là multibyte và không có char tương ứng với sự kết hợp của bạn \xe9cộng với không gian sau.

Tại sao nó phải thành công trong cả utf-8 và latin-1?

Ở đây làm thế nào cùng một câu trong utf-8:

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

Latin-1 là một họ mã hóa byte đơn, vì vậy mọi thứ trong đó phải được định nghĩa trong UTF-8. Nhưng tại sao đôi khi Latin-1 thắng?
Reihan_amn

11

Nếu lỗi này phát sinh khi thao tác với một tệp vừa được mở, hãy kiểm tra xem bạn đã mở nó ở 'rb'chế độ chưa


2
Nhờ câu trả lời này, đã có thể tránh được lỗi của, UnicodeDecodeError: codec 'utf-8' không thể giải mã byte 0xd7 ở vị trí 2024079: byte tiếp tục không hợp lệ bởi soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Philip

6

Điều này cũng xảy ra với tôi, trong khi tôi đang đọc văn bản có chứa tiếng Do Thái từ một .txttập tin.

Tôi đã bấm: file -> save asvà tôi đã lưu tệp này dưới dạng UTF-8mã hóa


5

Lỗi mã utf-8 thường xuất hiện khi phạm vi của các giá trị số vượt quá 0 đến 127.

lý do để đưa ra ngoại lệ này là:

1) Nếu điểm mã <128, mỗi byte giống với giá trị của điểm mã. 2) Nếu điểm mã là 128 hoặc lớn hơn, chuỗi Unicode không thể được biểu diễn trong mã hóa này. (Python tăng ngoại lệ UnicodeEncodeError trong trường hợp này.)

Để khắc phục điều này, chúng tôi có một bộ mã hóa, được sử dụng rộng rãi nhất là "Latin-1, còn được gọi là ISO-8859-1"

Vì vậy, ISO-8859-1 Unicode points 0 Hay255 giống hệt với các giá trị Latin-1, do đó, việc chuyển đổi sang mã hóa này chỉ đơn giản yêu cầu chuyển đổi điểm mã thành giá trị byte; nếu gặp một điểm mã lớn hơn 255, chuỗi không thể được mã hóa thành tiếng Latin-1

khi ngoại lệ này xảy ra khi bạn đang cố tải một tập dữ liệu, hãy thử sử dụng định dạng này

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

Thêm kỹ thuật mã hóa vào cuối cú pháp, sau đó chấp nhận tải tập dữ liệu.


Xin chào và chào mừng đến với SO! Vui lòng chỉnh sửa câu trả lời của bạn để đảm bảo rằng nó cải thiện các câu trả lời khác đã có trong câu hỏi này.
hongsy

4

Sử dụng cái này, nếu nó hiển thị lỗi của UTF-8

pd.read_csv('File_name.csv',encoding='latin-1')

-1

Trong trường hợp này, tôi đã cố gắng thực thi một .py kích hoạt đường dẫn / file.sql.

Giải pháp của tôi là sửa đổi mã hóa của file.sql thành "UTF-8 không có BOM" và nó hoạt động!

Bạn có thể làm điều đó với Notepad ++.

tôi sẽ để lại một phần mã của tôi

/ /

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

con trỏ = con.cthon () sqlfile = open (path, 'r')

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.