为啥python3k的pyserial返回字节而python2k返回字符串?
Posted
技术标签:
【中文标题】为啥python3k的pyserial返回字节而python2k返回字符串?【英文标题】:Why does pyserial for python3k return bytes while python2k returns strings?为什么python3k的pyserial返回字节而python2k返回字符串? 【发布时间】:2014-10-23 07:40:34 【问题描述】:我正在尝试移植 https://github.com/thearn/Python-Arduino-Command-API 到 python 3,到目前为止,我已经将它导入到没有错误的地步,我尝试运行闪烁示例 found here,但我总是会收到类型错误。
我想我已经把范围缩小到了。
python 2.7.8 的 PySerial 2.7 中的 readline 函数返回一个字符串,python 3.3 的 PySerial 2.7 中的 readline 函数返回字节。
Python 2
>>> import serial
>>> serial.VERSION
'2.7'
>>> ser= serial.Serial(port='COM4')
>>> ser.readline()
'0\r\n'
>>> type(ser.readline())
<type 'str'>
Python 3
>>> import serial
>>> serial.VERSION
'2.7'
>>> ser = serial.Serial(port='COM4')
>>> ser.readline()
b'0\r\n'
>>> type(ser.readline())
<class 'bytes'>
我已经检查了 pyserial 的 python 2 和 python 3 实现的 readline 函数的源代码,它们似乎都应该返回字节,因为每个字节的最后一行是 return bytes(line)
,这是唯一的返回语句整个函数。
我的问题:为什么 PySerial 2.7 的 readline 函数在 python2 和 python3 中返回不同的结果?
【问题讨论】:
如果你以正确的方式提问,你不会得到不同的结果。在 2.7 中,bytes == str
。所以 type(ser.readline()) == bytes
在 2.7 和 3.x 中都是 True
。
【参考方案1】:
这是因为在 Python 3.x 中,文本始终是 Unicode 并由 str 类型表示,而二进制数据由 bytes 类型表示。此功能不同于 Python 2.x 版本。
在您的示例中,ser.readline()
实际上返回二进制数据。
【讨论】:
【参考方案2】:这是 Python 2 和 3 之间的主要区别之一。
来自https://docs.python.org/3.0/whatsnew/3.0.html:
Python 3.0 使用文本和(二进制)数据的概念,而不是 Unicode 字符串和 8 位字符串。所有文本都是 Unicode;然而,编码的 Unicode 被表示为二进制数据。用来保存文本的类型是str,用来保存数据的类型是字节。与 2.x 情况的最大区别在于,任何在 Python 3.0 中混合文本和数据的尝试都会引发 TypeError,而如果您要在 Python 2.x 中混合 Unicode 和 8 位字符串,如果 8 位string 恰好只包含 7 位 (ASCII) 字节,但如果它包含非 ASCII 值,您会得到 UnicodeDecodeError。多年来,这种特定于价值的行为引起了无数悲伤的面孔。
您将在上面链接的“文本与数据而不是 Unicode 与 8 位”部分中找到完整的说明。
【讨论】:
【参考方案3】:在 python 3 中执行套接字程序时,我遇到了这个问题。当我接收流时,我最终使用 decode() 函数使其正常工作。
retval = sock.recv(1024).decode()
解码非常有用。不确定它是否适用于您的情况,但请尝试一下。
【讨论】:
以上是关于为啥python3k的pyserial返回字节而python2k返回字符串?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 InputStream#read() 返回一个 int 而不是一个字节?
为啥 .NET 的 RandomNumberGenerator.GetBytes 方法将其结果分配给一个字节数组参数,而不是返回一个新的字节数组?