readline() 导致 pyserial python 2 和 3 兼容性
readline() result in pyserial python 2 and 3 compatibility
我正在编写一个简单的代码来使用 pyserial 与几个相同的 RS-232 设备进行通信。我发送命令并得到回复。回复中的第 6 个元素是我的 ID。此 ID 用于定义我正在与哪个设备通话。
我想要一个更优雅的语法,将第 6 个元素提取为 Python 3 和 Python 2 中的整数。有没有更优雅的方法然后只写两个不同的函数我根据使用的 Python 调用。
如果Python 3
>>> port = Serial('/dev/cu.usbserial4')
>>> port.baudrate = 9600
>>> port.timeout = 0.4
>>> port.write(b"/1?80\r")
6
>>> reply = port.readline()
>>> reply
b'\xff/0`ZA4\x03\r\n'
>>> reply[6]
52
>>> chr(reply[6])
'4'
>>> int(chr(reply[6]))
4
如果Python 2
>>> port = Serial('/dev/cu.usbserial4')
>>> port.baudrate = 9600
>>> port.timeout = 0.4
>>> port.write(b"/1?80\r")
6
>>> reply = port.readline()
>>> reply
'\xff/0`ZA4\x03\r\n'
>>> reply[6]
'4'
>>> int(reply[6])
4
port.readline()
的结果是二进制数据(在Python2中称为str
,在Pyton 3中称为bytes
)。所以问题是如何以 Python 2 和 Python 3 兼容的方式处理二进制数据。有多种方法可以做到这一点。对于 Python 2 和 3.
,以下三个解决方案都给出了相同的结果(数字 = 52)
对于二进制数据
解决方案 1
如果您知道数据是如何编码的,您就可以正确解码它。这将导致 "unicode text string"(在 Python 2 中称为 unicode
,在 Python 3 中称为 str
)。
reply = b'\xff/0`ZA4\x03\r\n'
decoded_reply = reply.decode('latin-1')
number = ord(decoded_reply[6])
解决方案 2
更通用的解决方案是使用 struct
模块解码二进制数据:
import struct
reply = b'\xff/0`ZA4\x03\r\n'
number = struct.unpack('B', reply[6:7])[0]
解决方案 3
您还可以使用 six
模块:
Six is a Python 2 and 3 compatibility library. It provides utility functions for smoothing over the differences between the Python versions with the goal of writing Python code that is compatible on both Python versions. See the documentation for more information on what is provided.
例如:
import six
reply = b'\xff/0`ZA4\x03\r\n'
number = six.byte2int(reply[6:7])
请注意,此库还为许多其他兼容性问题提供了解决方案。因此,如果您正在编写需要 Python 2 和 3 兼容的大型应用程序,那当然值得研究一下。
对于 ASCII 数据
如果您的 ID 是 0-9 范围内的 ASCII-coded 数字,则以下解决方案是最佳选择。在这种情况下使用 struct
没有任何意义。
reply = '\xff/0`ZA4\x03\r\n' # input in Python 2
reply = b'\xff/0`ZA4\x03\r\n' # input in Python 3
number = int(reply.decode('latin-1')[6])
# or if your reply is mixed binary and ASCII and you're only interested in byte 6:
number = int(reply[6:7].decode('ascii'))
在 Python 2 和 3 中,数字都是 4。
或者,您可以使用 "binary" 解决方案之一并从结果中减去 48(=ASCII 字符“0”)。
(以上所有示例均使用 Python 2.7 和 3.7 进行了测试)
我正在编写一个简单的代码来使用 pyserial 与几个相同的 RS-232 设备进行通信。我发送命令并得到回复。回复中的第 6 个元素是我的 ID。此 ID 用于定义我正在与哪个设备通话。
我想要一个更优雅的语法,将第 6 个元素提取为 Python 3 和 Python 2 中的整数。有没有更优雅的方法然后只写两个不同的函数我根据使用的 Python 调用。
如果Python 3
>>> port = Serial('/dev/cu.usbserial4')
>>> port.baudrate = 9600
>>> port.timeout = 0.4
>>> port.write(b"/1?80\r")
6
>>> reply = port.readline()
>>> reply
b'\xff/0`ZA4\x03\r\n'
>>> reply[6]
52
>>> chr(reply[6])
'4'
>>> int(chr(reply[6]))
4
如果Python 2
>>> port = Serial('/dev/cu.usbserial4')
>>> port.baudrate = 9600
>>> port.timeout = 0.4
>>> port.write(b"/1?80\r")
6
>>> reply = port.readline()
>>> reply
'\xff/0`ZA4\x03\r\n'
>>> reply[6]
'4'
>>> int(reply[6])
4
port.readline()
的结果是二进制数据(在Python2中称为str
,在Pyton 3中称为bytes
)。所以问题是如何以 Python 2 和 Python 3 兼容的方式处理二进制数据。有多种方法可以做到这一点。对于 Python 2 和 3.
对于二进制数据
解决方案 1
如果您知道数据是如何编码的,您就可以正确解码它。这将导致 "unicode text string"(在 Python 2 中称为 unicode
,在 Python 3 中称为 str
)。
reply = b'\xff/0`ZA4\x03\r\n'
decoded_reply = reply.decode('latin-1')
number = ord(decoded_reply[6])
解决方案 2
更通用的解决方案是使用 struct
模块解码二进制数据:
import struct
reply = b'\xff/0`ZA4\x03\r\n'
number = struct.unpack('B', reply[6:7])[0]
解决方案 3
您还可以使用 six
模块:
Six is a Python 2 and 3 compatibility library. It provides utility functions for smoothing over the differences between the Python versions with the goal of writing Python code that is compatible on both Python versions. See the documentation for more information on what is provided.
例如:
import six
reply = b'\xff/0`ZA4\x03\r\n'
number = six.byte2int(reply[6:7])
请注意,此库还为许多其他兼容性问题提供了解决方案。因此,如果您正在编写需要 Python 2 和 3 兼容的大型应用程序,那当然值得研究一下。
对于 ASCII 数据
如果您的 ID 是 0-9 范围内的 ASCII-coded 数字,则以下解决方案是最佳选择。在这种情况下使用 struct
没有任何意义。
reply = '\xff/0`ZA4\x03\r\n' # input in Python 2
reply = b'\xff/0`ZA4\x03\r\n' # input in Python 3
number = int(reply.decode('latin-1')[6])
# or if your reply is mixed binary and ASCII and you're only interested in byte 6:
number = int(reply[6:7].decode('ascii'))
在 Python 2 和 3 中,数字都是 4。
或者,您可以使用 "binary" 解决方案之一并从结果中减去 48(=ASCII 字符“0”)。
(以上所有示例均使用 Python 2.7 和 3.7 进行了测试)