【问题标题】:Convert an int value to unicode将 int 值转换为 unicode
【发布时间】:2013-07-11 18:12:41
【问题描述】:

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

【问题讨论】:

  • Python2 还是 Python3? (猜测 Python2,但差别很大)你确定unichr 是呼叫崩溃了吗?您如何实际发送 unichr 返回的数据?
  • unichr() 在 Python 3 中不存在,所以这是 Python 2。unichr() 在 Python 3 中被命名为 chr()(转换为 Unicode 字符)。

标签: python character-encoding ascii pyserial


【解决方案1】:

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

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

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

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

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

【讨论】:

  • str(integer).encode("utf-8").decode("utf-8"),虽然丑陋,但可以在 Python 2 和 3 上运行,而上述代码只能在 Python 2 上运行。
【解决方案2】:

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

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

【讨论】:

  • @user2578666:如果回复对您有用并且您将其标记为已接受,那么投票也很公平。欢迎使用 StackOverflow!
  • 还没有代表。必须赢得它:-)
  • @user2578666:我明白了——我不记得这条规则了。愿你名声快速增长。 :)
  • chr(32) 正在返回 ' ' 空白空间,其他数字工作正常。如何克服价值 32?
  • chr(32) 也是 0x20,这是空格字符 - 你希望看到什么?
【解决方案3】:

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

必须首先对 unicode 字符进行编码以获得 byte 字符,并且该编码失败,因为您使用的值超出了 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'

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

【讨论】:

  • 我猜你的意思是“字节”,而不是“字节字符”? “字节字符”不是一个常见的表达方式,几乎是一个oxymoron。此外,默认编码不必是 ASCII:它的官方名称是 sys.getdefaultencoding()
  • @EOL:这是 Python 2,这是一个字符串对象,它实际上是一个字节序列。但是循环它会给你长度为 1 的字符串;字节字符。
  • @EOL:Python 2 上的默认编码 ASCII,当涉及到隐式编码(连接字符串和 unicode,比较相等等)时。
  • @EOL:不要将其与print 语句/函数编码为sys.stdout 的编解码器混淆。
  • 你有参考说明这个吗?我一直在寻找它。
【解决方案4】:

我认为最好的解决方案是明确地说你想将一个数字表示为一个字节(和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(文件, socket, terminal,…)——Python 3 中的chr() 等价于问题的Python 2 unichr()struct 解决方案的优点是无论 Python 的版本如何,都能正确生成一个字节。如果您想使用chr() 通过串行端口发送数据,您需要控制随后必须进行的编码。当 Python 3 使用的默认编码是 UTF-8(我认为是这种情况)时,该代码可能会起作用,但这是因为代码点小于 256 的 Unicode 字符可以在 UTF 中编码为单个字节-8。这增加了我不推荐的不必要的微妙和复杂层(它使代码更难理解,并且在必要时进行调试)。

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

【讨论】:

  • Bravo @EOL - C++ 继承的关于 C 的(可能有很多)误导性事情之一是长度为 1 的字符串和单个字符之间没有任何区别 - 两个文本n 本地编码 - 和一个字节。
猜你喜欢
  • 1970-01-01
  • 2021-11-04
  • 2013-05-04
  • 1970-01-01
  • 2015-09-14
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多