2010-10-14 33 views
5

Tôi đang sử dụng ứng dụng Django để xuất chuỗi thành tệp CSV. Chuỗi là một thông báo được gửi qua một mẫu giao diện người dùng. Tuy nhiên, tôi đã nhận được lỗi này khi một báo giá đơn unicode được cung cấp trong đầu vào.Xuất CSV Unicode bằng Python (sử dụng Django)

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' 
    in position 200: ordinal not in range(128) 

Tôi đã cố gắng chuyển đổi unicode thành ascii bằng cách sử dụng mã bên dưới, nhưng vẫn gặp lỗi tương tự.

UnicodeEncodeError: 'ascii' codec can't encode characters in 
position 0-9: ordinal not in range(128) 

Tôi đã sàng lọc hàng chục trang web và học được rất nhiều về unicode, tuy nhiên, tôi vẫn không thể chuyển đổi unicode này thành ascii. Tôi không quan tâm nếu thuật toán loại bỏ các ký tự unicode. Các dòng nhận xét cho biết một số tùy chọn khác nhau mà tôi đã thử, nhưng lỗi vẫn tồn tại.

import csv 
import unicodedata 

... 

#message = unicode(unicodedata.normalize(
#       'NFKD',contact.message).encode('ascii','ignore')) 
#dmessage = (contact.message).encode('utf-8','ignore') 
#dmessage = contact.message.decode("utf-8") 
#dmessage = "%s" % dmessage 
dmessage = contact.message 

csv_writer.writerow([ 
     dmessage, 
]) 

Có ai có lời khuyên nào về việc xóa ký tự unicode để tôi có thể xuất chúng sang CSV không? Vấn đề dường như dễ dàng này đã khiến tôi quay đầu. Bất kỳ sự giúp đỡ nào cũng được đánh giá cao. Cảm ơn, Joe

+0

Cảm ơn bạn đã sửa chữa Glenn –

Trả lời

7

Bạn không thể mã hóa ký tự Unicode u'\u2019' (Dấu ngoặc kép đơn phải là U + 2019) thành ASCII, vì ASCII không có ký tự đó trong nó. ASCII chỉ là bảng chữ cái La tinh cơ bản, chữ số và dấu chấm câu; bạn không nhận được bất kỳ chữ cái có dấu hoặc 'dấu ngoặc kép thông minh' nào giống như ký tự này.

Vì vậy, bạn sẽ phải chọn một chế độ mã hóa khác. Bây giờ bình thường, điều hợp lý để làm sẽ là xuất sang UTF-8, có thể chứa bất kỳ ký tự Unicode nào. Thật không may cho bạn nếu người dùng mục tiêu của bạn đang sử dụng Office (và họ có thể là), họ sẽ không thể đọc các ký tự được mã hóa UTF-8 trong CSV. Thay vào đó, Excel sẽ đọc các tệp bằng cách sử dụng trang mã mặc định của hệ thống cho máy đó (cũng được biết đến là trang mã "ANSI") và kết thúc bằng mojibake như ’ thay vì .

Điều đó có nghĩa là bạn phải đoán trang mã mặc định của hệ thống của người dùng nếu bạn muốn các ký tự hiển thị chính xác. Đối với người dùng phương Tây, đó sẽ là trang mã 1252. Người dùng có cài đặt Windows không phải là phương Tây sẽ thấy các ký tự sai, nhưng bạn không thể làm gì khác (ngoài việc tổ chức một chiến dịch viết thư cho Microsoft để chỉ bỏ những điều vô nghĩa với ANSI đã và đang sử dụng UTF-8 như mọi người khác).

Trang mã 1252 có thể chứa U + 2019 (), nhưng rõ ràng có nhiều ký tự hơn mà nó không thể đại diện. Để tránh nhận được UnicodeEncodeError đối với những ký tự đó, bạn có thể sử dụng đối số ignore (hoặc replace để thay thế chúng bằng dấu chấm hỏi).

dmessage= contact.message.encode('cp1252', 'ignore') 

cách khác, từ bỏ và loại bỏ tất cả ký tự ASCII, để mọi người được một kinh nghiệm không kém phần xấu không phân biệt ngôn ngữ:

dmessage= contact.message.encode('ascii', 'ignore') 
+1

@bobince: "đoán trang mã mặc định của hệ thống của người dùng" ... bạn đã gặp phải vấn đề gì khi cố gắng thực hiện tác vụ này với 'locale.getpreferredencoding()' hoặc 'locale.getdefaultlocale() [1]'? –

+2

@ John: Tôi đang suy nghĩ nếu Django có liên quan, chúng tôi đang nói về một ứng dụng phía máy chủ và không có đảm bảo mã hóa mặc định của máy chủ là bất cứ điều gì giống như của khách hàng. (Trong trường hợp phổ biến mà máy khách là Windows và máy chủ không phải là, các mã hóa sẽ không bao giờ khớp.) – bobince

+1

@bobince: Câu hỏi không bao giờ được chỉ định sử dụng; cho tất cả chúng ta biết các tập tin csv chỉ có thể được cho các mục đích kiên trì và sẽ chỉ được sử dụng trong nội bộ. –

2

Mã hóa là một nỗi đau, nhưng nếu bạn đang làm việc ở django bạn đã thử smart_unicode(str) từ django.utils.encoding? Tôi thấy rằng thường là lừa.

Tùy chọn duy nhất khác mà tôi tìm thấy là sử dụng trăn gắn sẵn encode()decode() cho các chuỗi, nhưng bạn phải chỉ định mã hóa cho các chuỗi đó và thành thật, đó là một nỗi đau.

+0

Cảm ơn Waffel Paradox, tôi sẽ cung cấp cho smart_unicode một ảnh và cho bạn biết cách thực hiện. –

1

[caveat: Tôi không phải là một djangoist ; django có thể có một giải pháp tốt hơn].

chung câu trả lời không django cụ thể:

Nếu bạn có một số smallish của ký tự ASCII được biết đến và có sử dụng chấp nhận được tương đương ASCII cho họ, bạn có thể thiết lập một bảng dịch và sử dụng unicode.translate phương pháp:

smashcii = { 
    0x2019 : u"'", 
    # etc 
    # 

smashed = input_string.translate(smashcii) 
+0

Tôi sẽ phải cung cấp cho phương pháp này một shot. Có thể giúp tôi vượt qua vấn đề này ít nhất. Cảm ơn bạn đã gợi ý cho bạn. –

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