关于python:将int值转换为unicode

Convert an int value to unicode

我正在使用pyserial,需要发送一些小于255的值。如果我发送int本身,则会发送int的ascii值。所以现在我把int转换成一个unicode值,并通过串行端口发送它。

1
2
3
4
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的最佳方法是什么?


在python 2中-首先将其转换为字符串,然后转换为unicode。

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

我认为最好的方式。与任何整数一起使用,如果将字符串作为输入,则加号仍然有效。

由于注释更新了编辑:对于python 2和3——这两种方法都适用,但有点混乱:

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


只要一个int小于256,就用chr(somenumber)得到它的1字节值。然后,Pyserial会很好地发送它。

如果您想通过pyserial发送东西,那么最好查看标准库中的struct模块,它可以处理endian问题、打包问题以及您可能需要的每种数据类型(1字节或以上)的编码。


使用chr()函数;您发送的值小于256但大于128,但正在创建Unicode字符。

然后,必须首先对Unicode字符进行编码,才能获得字节字符,并且编码失败,因为您使用的值超出了ASCII范围(0-127):

1
2
3
4
>>> 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(),则创建一个一个字符的字节字符串,而不必进行隐式编码:

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

您可能希望研究的另一种方法是struct模块,特别是当您需要发送大于255的整数值时:

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

例如,上面的示例将一个整数按网络字节顺序打包成无符号短字符串。


我认为最好的解决方案是明确地说,您希望将数字表示为字节(而不是字符):

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

这使得您的代码在python 2和python 3中都可以工作(在python 3中,结果应该是一个bytes对象)。在python 3中,另一种选择是使用新的bytes([128])创建值为128的单字节。

我不太喜欢chr()解决方案:在python中,它们生成(字符,而不是字节)字符串,在将其发送到任何地方之前需要对其进行编码(文件、套接字、终端等)。python中的chr()相当于问题的python(2)unichr()struct解决方案的优点是,无论Python的版本是什么,都能正确地生成一个字节。如果您想使用chr()通过串行端口发送数据,则需要控制随后必须进行的编码。当python使用的默认编码是utf-8(我认为是这种情况)时,代码可能会工作,但这是因为小于256的代码点的Unicode字符可以用utf-8编码为单个字节。这增加了一个我不推荐的不必要的微妙和复杂的层(它使代码更难理解,如果必要的话,调试)。

因此,我强烈建议您使用上面的方法(Steve Barnes和Martijn Pieters也曾暗示过):它清楚地表明您想要生成一个字节(而不是字符)。即使您使用python 3运行代码,它也不会给您带来任何惊喜,而且它使您的意图更加清晰和明显。