2013-07-13 66 views
12

Tôi đang sử dụng bộ xử lý và cần gửi một số giá trị nhỏ hơn 255. Nếu tôi gửi bản thân int thì giá trị ascii của int sẽ được gửi. Vì vậy, bây giờ tôi đang chuyển đổi int thành một giá trị unicode và gửi nó thông qua cổng nối tiếp.Chuyển đổi giá trị int thành unicode

unichr(numlessthan255); 

However it throws this error: 
'ascii' codec can't encode character u'\x9a' in position 24: ordinal not in range(128) 

Làm cách nào tốt nhất để chuyển đổi int thành unicode?

+0

python2 hoặc Python3? (đoán Python2, nhưng làm cho khá sự khác biệt) Bạn có chắc chắn 'unichr' là cuộc gọi bị rơi? Làm thế nào bạn đang thực sự gửi dữ liệu trả về unichr? –

+2

'unichr()' không tồn tại trong Python 3, vì vậy đây là Python 2. 'unichr()' được đặt tên 'chr()' trong Python 3 (chuyển đổi thành một ký tự Unicode). – EOL

Trả lời

9

Chỉ cần sử dụng chr(somenumber) để nhận được giá trị 1 byte của int miễn là nó nhỏ hơn 256. pySerial sau đó sẽ gửi tiền phạt.

Nếu bạn đang xem xét việc gửi mọi thứ qua pySerial thì ý tưởng tốt để xem mô-đun cấu trúc trong thư viện chuẩn. có khả năng cần nó là 1 byte hoặc hơn.

+0

hoạt động nhờ rất nhiều – user2578666

+0

@ user2578666: Nếu một câu trả lời hữu ích cho bạn và bạn đánh dấu nó là được chấp nhận, nó chỉ là công bằng để bỏ phiếu quá. Chào mừng bạn đến với StackOverflow! – EOL

+1

Không có đại diện nào.Hãy kiếm tiền :-) – user2578666

8

Sử dụng số chr() function thay thế; bạn đang gửi một giá trị nhỏ hơn 256 nhưng nhiều hơn 128, nhưng đang tạo một ký tự Unicode.

Nhân vật unicode đã để sau đó được mã hóa đầu tiên để có được một byte nhân vật , và mã hóa mà không thành công vì bạn đang sử dụng một giá trị bên ngoài phạm vi ASCII (0-127):

>>> str(unichr(169)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa9' in position 0: ordinal not in range(128) 

Đây là hành vi Python 2 bình thường; khi cố gắng chuyển đổi chuỗi unicode thành chuỗi byte, mã hóa ngầm sẽ diễn ra và mã hóa mặc định là ASCII.

Nếu bạn đã sử dụng chr() thay vào đó, bạn tạo một chuỗi byte của một ký tự và mã hóa tiềm ẩn không không phải diễn ra:

>>> str(chr(169)) 
'\xa9' 

Một phương pháp mà bạn có thể muốn xem xét là struct module, đặc biệt là nếu bạn cần phải gửi các giá trị số nguyên hơn hơn 255:

>>> struct.pack('!H', 1000) 
'\x03\xe8' 

Ví dụ trên gói một số nguyên vào một thứ tự byte ngắn chưa được ký trong mạng, chẳng hạn.

+0

Tôi đoán bạn có nghĩa là "byte", không phải là "một ký tự byte"? "ký tự byte" không phải là biểu thức chung và gần như là [oxymoron] (http://stackoverflow.com/questions/4545661/unicodedecodeerror-when-redirecting-to-file/4546129#4546129). Hơn nữa, mã hóa mặc định không phải là ASCII: nó chính thức là 'sys.getdefaultencoding()'. – EOL

+0

@EOL: Đây là Python 2, đây là một đối tượng chuỗi, mà thực sự là một chuỗi các byte. Nhưng lặp lại nó cung cấp cho bạn các chuỗi có độ dài 1; ký tự byte. –

+0

@EOL: Mã hóa mặc định ** là ** ASCII trên Python 2, khi nói đến mã hóa ẩn (nối chuỗi và unicode, so sánh cho bình đẳng, vv). –

6

Tôi nghĩ rằng giải pháp tốt nhất là phải rõ ràng và nói rằng bạn muốn để đại diện cho một số như là một byte (và not as a character):

>>> import struct 
>>> struct.pack('B', 128) 
>>> '\x80' 

Điều này làm cho việc mã của bạn trong cả Python 2 và Python 3 (trong Python 3, kết quả là, như nó phải, một đối tượng bytes). Một thay thế, bằng Python 3, sẽ được sử dụng mới bytes([128]) để tạo ra một byte đơn có giá trị 128.

Tôi không phải là một fan hâm mộ lớn của chr() giải pháp: in Python 3, họ tạo ra một (nhân vật, chứ không phải byte) chuỗi cần phải là encoded trước khi gửi bất kỳ nơi nào (tệp, ổ cắm, thiết bị đầu cuối, ...) - chr() bằng Python 3 tương đương với vấn đề Python 2 unichr() của câu hỏi. Giải pháp struct có lợi thế là tạo ra một byte một cách chính xác bất kể phiên bản của Python. Nếu bạn muốn gửi dữ liệu qua cổng nối tiếp với chr(), bạn cần có quyền kiểm soát mã hóa phải diễn ra sau đó.Mã có thể hoạt động khi mã hóa mặc định được sử dụng bởi Python 3 là UTF-8 (mà tôi nghĩ là trường hợp), nhưng điều này là do thực tế là các ký tự Unicode của điểm mã nhỏ hơn 256 có thể được mã hóa thành một byte đơn trong UTF -số 8. Điều này cho biết thêm một lớp không cần thiết của sự tinh tế và phức tạp mà tôi không khuyên bạn nên (nó làm cho mã khó hiểu hơn và, nếu cần, gỡ lỗi). Vì vậy, tôi đặc biệt khuyên bạn nên sử dụng cách tiếp cận ở trên (cũng được gợi ý bởi Steve Barnes và Martijn Pieters): nó cho thấy rõ ràng rằng bạn muốn tạo ra một byte (và không phải là ký tự). Nó sẽ không cung cấp cho bạn bất kỳ bất ngờ ngay cả khi bạn chạy mã của bạn với Python 3, và nó làm cho ý định của bạn rõ ràng hơn và rõ ràng hơn.

+1

Bravo @EOL - một trong số, (có thể là nhiều) , những điều gây hiểu lầm về C mà C++ thừa hưởng là thiếu bất kỳ sự phân biệt nào giữa một chuỗi có độ dài là 1, một ký tự đơn - cả hai văn bản n mã hóa cục bộ - và một byte. –

24

Trong Python 2 - Biến nó thành chuỗi đầu tiên, sau đó thành unicode.

str(integer).decode("utf-8") 

Cách tốt nhất tôi nghĩ. Hoạt động với bất kỳ số nguyên nào, cộng với vẫn hoạt động nếu bạn đặt một chuỗi vào làm đầu vào.

Cập nhật chỉnh sửa do một lời nhận xét: Đối với Python 2 và 3 - Đây hoạt động trên cả nhưng một chút lộn xộn:

str(integer).encode("utf-8").decode("utf-8") 
+3

'str (số nguyên) .encode (" utf-8 "). Giải mã (" utf-8 ")', trong khi xấu xí, sẽ hoạt động trên Python 2 và 3, trong khi ở trên sẽ chỉ hoạt động trên Python 2. –