我正在使用pyserial并且需要发送一些小于255的值。如果我发送int本身,则发送int的ascii值。所以现在我将int转换为unicode值并通过串口发送。
unichr(numlessthan255);
However it throws this error:
'ascii' codec can't encode character u'\x9a' in position 24: ordinal not in range(128)
将int转换为unicode的最佳方法是什么?
答案 0 :(得分:29)
在Python 2中 - 首先将其转换为字符串,然后转换为unicode。
str(integer).decode("utf-8")
我认为最好的方式。适用于任何整数,如果您输入一个字符串作为输入,则仍然有效。
由于评论而更新了编辑:对于Python 2和3 - 这适用于两者但有点混乱:
str(integer).encode("utf-8").decode("utf-8")
答案 1 :(得分:14)
只要使用chr(somenumber)
获取int的1字节值,只要它小于256. pySerial将发送它。
如果您正在通过pySerial发送内容,那么查看标准库中的结构模块是一个非常的好主意,它会处理endian问题,包装问题以及几乎所有的编码您可能需要的数据类型为1个字节或更长。
答案 2 :(得分:10)
使用chr()
function代替;您发送的值小于256但大于128,但正在创建Unicode字符。
然后必须首先编码unicode字符以获取字节字符,并且该编码失败,因为您使用的值超出了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)
这是正常的Python 2行为;尝试将unicode字符串转换为字节字符串时,必须进行隐式编码,默认编码为ASCII。
如果您改为使用chr()
,则创建一个字符的字符串,并且不的隐式编码必须发生:
>>> str(chr(169))
'\xa9'
您可能想要研究的另一种方法是struct
module,特别是如果您需要发送大于的整数值而不是255:
>>> struct.pack('!H', 1000)
'\x03\xe8'
上面的示例将整数打包为网络字节顺序中的无符号短整数,例如。
答案 3 :(得分:10)
我认为最好的解决方案是明确表示你想将一个数字表示为一个字节(和not as a character):
>>> import struct
>>> struct.pack('B', 128)
>>> '\x80'
这使得您的代码在Python 2和Python 3中都能工作(在Python 3中,结果是,bytes对象)。在Python 3中,另一种方法是使用新的bytes([128])
来创建值为128的单个字节。
我不是chr()
解决方案的忠实粉丝:in Python 3,他们会产生一个(字符,而不是字节)字符串,需要encoded在将它发送到任何地方之前(文件,套接字,终端......) - Python 3中的chr()
等同于问题的有问题的Python 2 unichr()
。无论Python版本如何,struct
解决方案都具有正确生成字节的优势。如果要通过串行端口使用chr()
发送数据,则需要控制必须随后进行的编码。当Python 3使用的默认编码是UTF-8(我认为是这种情况)时,代码可能会起作用,但这是因为代码点小于256的Unicode字符可以编码为UTF中的单个字节-8。这增加了我不推荐的不必要的微妙和复杂的层次(它使代码更难理解,并且如果必要的话,调试)。
所以,我强烈建议你使用上面的方法(Steve Barnes和Martijn Pieters也暗示过):它清楚地表明你想要产生一个字节(而不是字符) )。即使您使用Python 3运行代码也不会给您带来任何惊喜,它会使您的意图更清晰,更明显。