2013-07-08 34 views
5

Tôi đã cố viết một kịch bản đơn giản có thể lưu đầu vào của người dùng (bắt nguồn từ iPhone) vào một tệp văn bản. Vấn đề tôi gặp phải là khi người dùng sử dụng biểu tượng Biểu tượng cảm xúc, nó phá vỡ toàn bộ sự việc.Chữ viết Python (iPhone) Biểu tượng cảm xúc vào một tập tin

Hệ điều hành: Ubuntu

Python Version: 2.7.3

Mã của tôi hiện nay trông như thế này

f = codecs.open(path, "w+", encoding="utf8") 
f.write("Desc: " + json_obj["description"]) 
f.close() 

Khi một nhân vật biểu tượng cảm xúc được truyền trong biến mô tả, tôi nhận được lỗi:

UnicodeEncodeError: codec 'ascii' không thể mã hóa các ký tự ở vị trí 7-8: thứ tự không nằm trong phạm vi (128)

Mọi trợ giúp có thể được đánh giá cao.

+0

Là 'json_obj [" description "]' a 'unicode' hoặc' str'? Nếu sau này, mã hóa là gì? Ngoài ra, bạn có thể 'in repr (json_obj [" description "])' ngay trước lỗi, vì vậy chúng ta có thể thấy những gì bạn đang thực sự cố gắng để in? – abarnert

+0

Ngoài ra, 'json_obj' đến từ đâu? Tên này ngụ ý mô-đun 'json' stdlib, nhưng thực tế là các khóa và giá trị rõ ràng là' str' ngụ ý rằng nó không phải… – abarnert

Trả lời

3

Vấn đề rất có thể xảy ra ở đây là json_obj["description"] thực sự là mã được mã hóa UTF-8 str, không phải là unicode. Vì vậy, khi bạn cố gắng write nó vào một tệp tin codecs -wrapped, Python phải giải mã nó từ str thành unicode để nó có thể mã hóa lại. Và đó là phần không thành công, bởi vì giải mã tự động đó sử dụng sys.getdefaultencoding(), là 'ascii'.

Ví dụ:

>>> f = codecs.open('emoji.txt', 'w+', encoding='utf-8') 
>>> e = u'\U0001f1ef' 
>>> print e 

>>> e 
u'\U0001f1ef' 
>>> f.write(e) 
>>> e8 = e.encode('utf-8') 
>>> e8 
'\xf0\x9f\x87\xaf' 
>>> f.write(e8) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 0: ordinal not in range(128) 

Có hai giải pháp khả thi ở đây.

Trước tiên, bạn có thể giải mã rõ ràng mọi thứ thành unicode càng sớm càng tốt. Tôi không chắc chắn nơi của bạn json_obj là đến từ, nhưng tôi nghi ngờ nó không thực sự là stdlib json.loads, bởi vì theo mặc định, mà luôn luôn cung cấp cho bạn unicode khóa và giá trị. Vì vậy, thay thế bất cứ điều gì bạn đang sử dụng cho JSON với các chức năng stdlib có thể sẽ giải quyết vấn đề.

Thứ hai, bạn có thể để mọi thứ dưới dạng đối tượng UTF-8 str và ở chế độ nhị phân. Nếu bạn biết bạn có UTF-8 ở mọi nơi, chỉ cần open tệp thay vì codecs.open và viết mà không cần bất kỳ mã hóa nào.


Ngoài ra, bạn nên cân nhắc sử dụng io.open thay vì codecs.open. Nó có một số lợi thế, bao gồm:

  • Tăng ngoại lệ thay vì làm sai điều gì nếu bạn vượt qua giá trị không chính xác.
  • Thường nhanh hơn.
  • Tương thích về phía trước với Python 3.
  • Có một số sửa lỗi sẽ không bao giờ được chuyển ngược lại thành codecs.

Điểm bất lợi duy nhất là nó không tương thích ngược với Python 2.5. Trừ khi điều đó quan trọng với bạn, đừng sử dụng codecs.

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