python-3.x - 如何编写 Python 异步串行异步阅读器?
问题描述
我正在将一些 C++ 代码移植到 Python,并且我花了很长时间弄清楚如何为串行字节提供 onReceive 处理程序。我在用
import serial_asyncio
class Arduino: #comms is with an Arduino in serial mode)
async def connect(self, serial_port):
(self.serial_reader, self.serial_writer) = await
serial_asyncio.open_serial_connection(url=serial_port, baudrate=115200)
print("serial opened:", serial_port)
self.buffer = b""
async def recv(self, data):
self.buffer += data
self.process_buffer(self.buffer)
if __name__ == '__main__':
ardunio = Arduino("/dev/ttyS0")
loop = asyncio.get_event_loop()
loop.run_until_complete(ardunio.connect())
loop.run_forever()
但是我无法弄清楚如何将 recv 处理程序修补到读取中。我Qt,我可以:
connect(&QAbstractSocket::readyRead, &Arduino::handleBytes);
在节点中:
arduino.on('data', line => console.log(line))
在 Python 中,似乎没有任何明显的答案?如何将到达的串行端口字节传递给 Arduino.receive(self, data)?
解决方案
但是我无法弄清楚如何将 recv 处理程序修补到读取中。
open_serial_connection
不是基于回调的接口,它返回一对通过协程公开内容的流。这使您可以像编写阻塞代码一样与串行端口通信,即无需使用回调和缓冲区来构建数据。例如(未经测试):
async def main():
reader, writer = await serial_asyncio.connect(url="/dev/ttyS0", baudrate=115200)
# instead of: arduino.on('data', line => console.log(line))
# ...we can just read some data from the serial port
data = await reader.read(1024)
# ...and print it right here
print(repr(data))
asyncio.run(main())
像这样StreamReader.read
的协程看起来会阻塞等待数据,但实际上它们只是暂停当前协程并让事件循环做其他事情。这使您可以在等待数据从串行端口到达时轻松表达超时或进行其他处理。
如果您仍然需要回调,例如因为您需要与 C API 通信,您有两种选择:
使用底层
create_serial_connection
函数。它接受一个继承类型,asyncio.Protocol
您可以在其中定义钩子data_received
(作为回调,而不是协程),这与您对Arduino
类建模的方式很接近。继续使用协程 API,但用于
add_done_callback
注册回调以在协程准备好时运行。
后者的一个例子是:
async def main():
reader, writer = await serial_asyncio.connect(url="/dev/ttyS0", baudrate=115200)
# Python equivalent of arduino.on('data', x):
# 1. call reader.read() but don't await - instead, create a "future"
# which works like a JavaScript Promise
future = asyncio.ensure_future(reader.read(1024))
# register a done callback when the result is available
future.add_done_callback(future, lambda _: print(repr(future.result())))
# go do something else - here we wait for an event just so main()
# doesn't exit immediately and terminate our program
await asyncio.Event().wait()
asyncio.run(main())
但是除非你正在与 C 通信,否则我认为使用这种风格比普通的 async/await 没有优势。
推荐阅读
- javascript - 向 Restify conditionalHandler 添加多个中间件
- reactjs - 反应元素的动态渲染
- pyspark - PySpark:即使在转换类型之后,fillna 函数也不起作用
- java - 加载声音资源以播放它 Java
- bash - 将环境变量和函数打印为 bash 中的可执行命令
- android - PowerMock 参数 captor 为新 Intent 返回 null
- c# - 使用asp.net web api在Angular6中上传多个图像
- php - Mime 类型(限制/允许应用程序/八位字节流,即 .bin 和 .rar
- python - 无法安装不平衡学习
- java - Java空对象形成数组