32

我正在使用 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 的最佳方法是什么?

4

4 回答 4

32

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

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

我认为最好的方式。适用于任何整数,如果您将字符串作为输入,则仍然有效。

由于评论而更新了编辑:对于 Python 2 和 3 - 这适用于两者但有点混乱:

str(integer).encode("utf-8").decode("utf-8") 
于 2015-11-12T13:01:28.097 回答
24

chr(somenumber)只要它小于 256,就可以使用它来获取一个 1 字节的 int 值。pySerial 然后会很好地发送它。

如果您正在考虑通过 pySerial 发送内容,那么查看标准库中的 struct 模块是一个非常好的主意,它处理字节序问题、打包问题以及您可能需要的几乎每种数据类型的编码1 字节或以上。

于 2013-07-13T07:25:01.317 回答
11

请改用该chr()功能;您发送的值小于 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'

您可能想要研究的另一种方法是structmodule,特别是如果您需要发送大于255 的整数值:

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

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

于 2013-07-13T07:25:19.570 回答
11

我认为最好的解决方案是明确地说你想将一个数字表示为一个字节(而不是一个字符):

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

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

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

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

于 2013-07-13T07:53:31.997 回答