2012-05-02 20 views
60

Tôi đang cố gắng làm việc với tập dữ liệu rất lớn có một số ký tự không chuẩn trong đó. Tôi cần phải sử dụng unicode, theo thông số công việc, nhưng tôi bị bối rối. (Và hoàn toàn có thể làm việc đó hoàn toàn sai.)UnicodeDecodeError: 'ascii' codec không thể giải mã byte 0xd1 ở vị trí 2: thứ tự không nằm trong phạm vi (128)

tôi mở CSV sử dụng:

15  ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"') 

Sau đó, tôi cố gắng để mã hóa nó với:

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23]) 

tôi mã hóa tất cả mọi thứ ngoại trừ lat và lng bởi vì chúng cần được gửi tới API. Khi tôi chạy chương trình để phân tích cú pháp tập dữ liệu thành những gì tôi có thể sử dụng, tôi nhận được Traceback sau đây.

Traceback (most recent call last): 
    File "push_into_db.py", line 80, in <module> 
    main() 
    File "push_into_db.py", line 74, in main 
    district_map = buildDistrictSchoolMap() 
    File "push_into_db.py", line 32, in buildDistrictSchoolMap 
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23]) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128) 

Tôi nghĩ tôi nên nói với bạn rằng tôi đang sử dụng python 2.7.2 và đây là một phần của ứng dụng được xây dựng trên django 1.4. Tôi đã đọc một số bài viết về chủ đề này, nhưng không ai trong số họ dường như trực tiếp áp dụng. Chúng tôi rất trân trọng bất kỳ sự giúp đỡ nào.

Bạn cũng có thể muốn biết rằng một số ký tự không chuẩn gây ra vấn đề là Ñ và có thể là É.

+1

mã hóa tập tin ban đầu của bạn là gì? Tôi nghĩ rằng bạn nên giải mã nó theo mã hóa ban đầu và sau đó chuyển đổi thành utf 8 –

+0

có thể trùng lặp của [Encoding cho "'ascii' codec không thể mã hóa ký tự ... thứ tự không trong phạm vi (128)"] (http: // stackoverflow .com/questions/2513027/encoding-cho-ascii-codec-không-mã hóa-ký tự-thứ tự-không-trong-phạm vi128) [Ed .: và khoảng một tỷ người khác, quá, tôi chắc chắn.] –

Trả lời

119

Unicode không bằng UTF-8. Cái sau chỉ là mã hóa cho trước đây.

Bạn đang làm điều đó một cách sai lầm. Bạn đang đọc UTF-8- được mã hóa dữ liệu, vì vậy bạn phải giải mã Chuỗi được mã hóa UTF-8 thành chuỗi unicode.

Vì vậy, chỉ cần thay thế .encode bằng .decode và nó sẽ hoạt động (nếu .csv của bạn được mã hóa UTF-8).

Không có gì đáng xấu hổ. Tôi đặt cược 3 trong 5 lập trình viên gặp khó khăn tại sự hiểu biết đầu tiên này, nếu không muốn nói nhiều hơn nữa;)

Cập nhật: Nếu dữ liệu đầu vào của bạn là không UTF-8 mã hóa, sau đó bạn phải .decode() với mã hóa thích hợp, tất nhiên . Nếu không có gì được đưa ra, python giả định ASCII, rõ ràng là không thành công trên các ký tự không phải ASCII.

+0

lý do cho các lỗi được rằng Python đang cố gắng tự động giải mã nó từ mã hóa mặc định, ASCII, để nó sau đó có thể mã hóa nó như ông đã chỉ định, để UTF-8. Vì dữ liệu không phải là ASCII hợp lệ, nên nó không hoạt động. – agf

+7

chắc chắn, nhưng nếu nó được mã hóa UTF8 * * dữ liệu (như tôi đoán), sau đó '.decode ('utf-8')' nên làm các trick, cũng không? – ch3ka

+0

Chắc chắn, bạn có thể đúng. Tôi chỉ giải thích lý do tại sao bạn nhận được lỗi cụ thể trong tình huống này. – agf

48

Chỉ cần thêm dòng này để mã của bạn:

import sys 
reload(sys) 
sys.setdefaultencoding('utf-8') 
+2

cảm ơn bạn, điều này đã khắc phục sự cố của tôi –

+0

'AttributeError: module 'sys' không có thuộc tính 'setdefaultencoding' dường như không hoạt động trong Python 3 – skjerns

1

Lý do chính cho các lỗi là mã hóa mặc định giả bằng python là ASCII. Do đó, nếu dữ liệu chuỗi được mã hóa bởi encode('utf8') chứa ký tự nằm ngoài phạm vi ASCII, ví dụ: cho một chuỗi như 'hgvcj 터 파크 387', python sẽ ném lỗi vì chuỗi không ở định dạng mã hóa dự kiến.

Nếu bạn đang sử dụng phiên bản python sớm hơn so với phiên bản 3.5, một sửa chữa đáng tin cậy sẽ được thiết lập mã hóa mặc định giả bằng python để utf8:

import sys 
reload(sys) 
sys.setdefaultencoding('utf8') 
name = school_name.encode('utf8') 

Bằng cách này python sẽ có thể dự đoán ký tự trong một chuỗi nằm ngoài phạm vi ASCII.

Tuy nhiên, nếu bạn đang sử dụng phiên bản python 3.5 hoặc cao hơn, hàm reload() không có sẵn, vì vậy bạn sẽ phải sửa nó bằng cách sử dụng giải mã, ví dụ:

name = school_name.decode('utf8').encode('utf8') 
+0

sự khác biệt giữa câu trả lời của bạn và của tôi –

+0

Thêm chi tiết. Mọi người thường thấy chi tiết nhân quả hữu ích. Và mã của bạn hoạt động btw, không có mục đích xúc phạm. –

+0

tải lại có sẵn trong Python 3 bạn chỉ cần nhập nó. từ imp nhập khẩu reload – Meow

2

cho người dùng Python 3. bạn có thể làm

with open(csv_name_here, 'r', encoding="utf-8") as f: 
    #some codes 

nó hoạt động với bình quá :)

+0

cảm ơn bạn sir! đã sửa lỗi của tôi – fuzunspm

+0

Lần đầu tiên tôi giúp một người nào đó qua đây. cảm thấy tốt khi biết tôi đã giúp :) – screaminghard

Các vấn đề liên quan