2012-03-07 72 views
10

Tôi đang cố gắng chuyển đổi chuỗi byte đến chứa các ký tự không phải ascii thành chuỗi utf-8 hợp lệ sao cho tôi có thể đổ là json.mã hóa và giải mã chuỗi byte python

b = '\x80' 
u8 = b.encode('utf-8') 
j = json.dumps(u8) 

tôi mong đợi j là '\ xC2 \ x80' nhưng thay vào đó tôi nhận được:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128) 

Trong trường hợp của tôi, 'b' đến từ mysql thông qua bộ đệm giao thức google và được làm đầy với một số dữ liệu blob.

Bất kỳ ý tưởng nào?

EDIT: Tôi có khung ethernet được lưu trữ trong bảng mysql dưới dạng blob (vui lòng, mọi người, ở lại chủ đề và tiếp tục thảo luận tại sao có gói trong bảng). Bảng collation là utf-8 và lớp db (sqlalchemy, non-orm) là lấy dữ liệu và tạo các cấu trúc (bộ đệm giao thức google) lưu trữ các đốm màu như một con trăn 'str'. Trong một số trường hợp, tôi sử dụng bộ đệm giao thức trực tiếp với bất kỳ vấn đề nào. Trong các trường hợp khác, tôi cần phơi bày cùng một dữ liệu qua json. Những gì tôi nhận thấy là khi json.dumps() thực hiện điều đó, '\ x80' có thể được thay thế bằng char unicode không hợp lệ (\ ufffd iirc)

+0

Bạn cần cung cấp đoạn mã cho biết "sử dụng bộ đệm giao thức trực tiếp mà không có bất kỳ vấn đề nào" có nghĩa là. Bạn cần hiển thị đoạn mã bạn làm gì với bộ đệm giao thức để tạo ra 'json.dumps' tạo \ ufffd. Bạn cần phải nói chính xác những gì người tiêu dùng của gói JSONised này dự kiến ​​sẽ làm gì để khôi phục gói tin ban đầu. –

Trả lời

6

Sử dụng b.decode('name of source encoding') để có phiên bản unicode. Điều này thật bất ngờ khi tôi học nó. ví dụ:

In [123]: 'foo'.decode('latin-1') 
Out[123]: u'foo' 
+9

Hãy nhớ rằng: 'decode' chuyển từ byte thành unicode. 'encode' chuyển từ unicode sang byte. –

+0

@DanielRoseman Vâng, đó là lý do tại sao đây là câu trả lời cho câu hỏi. – Marcin

+0

Chắc chắn, tôi đã không tranh luận, chỉ cần cung cấp một số lời giải thích thêm cho OP. –

9

Bạn cần kiểm tra tài liệu về API phần mềm bạn đang sử dụng. BLOB là từ viết tắt: BINARY Đối tượng lớn.

Nếu dữ liệu của bạn thực tế là nhị phân, ý tưởng giải mã nó thành Unicode tất nhiên là vô nghĩa.

Nếu thực tế là văn bản, bạn cần biết mã hóa nào sẽ sử dụng để giải mã nó thành Unicode.

Sau đó, bạn sử dụng json.dumps(a_Python_object) ... nếu bạn mã hóa nó sang UTF-8 cho mình, json sẽ giải mã nó trở lại một lần nữa:

>>> import json 
>>> json.dumps(u"\u0100\u0404") 
'"\\u0100\\u0404"' 
>>> json.dumps(u"\u0100\u0404".encode('utf8')) 
'"\\u0100\\u0404"' 
>>> 

CẬP NHẬT về latin1:

u'\x80' là một điều khiển C1 vô nghĩa vô dụng ký tự - mã hóa rất khó có thể là Latin-1. Latin-1 là "bẫy và ảo tưởng" - tất cả các byte 8 bit được giải mã thành Unicode mà không làm tăng ngoại lệ. Đừng nhầm lẫn "công trình" và "không làm tăng ngoại lệ".

+0

thú vị. tôi đoán tôi có thể giữ nó đơn giản: in json.dumps ('\ x80'.decode (' latin1 ')) –

+1

@ kung-foo: Bạn không có bằng chứng cho thấy 'latin1' là mã hóa chính xác. –

+0

Vậy phương pháp mã hóa một chuỗi byte thành utf-8 là gì? –

2

Tôi nghĩ rằng những gì bạn đang cố gắng làm là giải mã đối tượng chuỗi của một số mã hóa. Bạn có biết mã hóa đó là gì không? Để có được đối tượng unicode.

unicode_b = b.decode('some_encoding') 

và sau đó mã hóa lại đối tượng unicode bằng cách sử dụng mã hóa utf_8 trở lại đối tượng chuỗi.

b = unicode_b.encode('utf_8') 

Sử dụng đối tượng unicode làm người dịch, không biết mã hóa ban đầu của chuỗi là gì tôi không biết chắc chắn nhưng có khả năng chuyển đổi sẽ không như mong đợi. Đối tượng unicode không có nghĩa là để chuyển đổi các chuỗi mã hóa này sang mã hóa khác.Tôi sẽ làm việc với đối tượng unicode giả sử bạn biết mã hóa là gì, nếu bạn không biết mã hóa là gì thì thực sự không phải là cách để tìm ra mà không dùng thử và lỗi, và sau đó chuyển trở lại chuỗi được mã hóa khi bạn muốn một đối tượng chuỗi trở lại.

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