serial_asyncio:将串行端口读入队列并从 main() 读取该队列不工作

serial_asyncio: read serial port into a queue and read that queue from main() not working

我有一个函数 do_serial() 从串行端口读取数据并将数据添加到队列中。我想在 main().

上处理该队列

我已经阅读了 serial_asyncio 文档并且有一个基本的 echo 类型证明,它读取串行数据并将其从单个异步函数回显。我无法开始工作的是更新队列并从 main().

读取队列

完成此工作后,我还想更新 main() 上的另一个队列并将其写入串行端口。这样 do_serial() 可以 运行 异步处理串口并且 main() 与队列交互。

这是我的代码:

import queue
import asyncio
import serial_asyncio

incoming_serial_queue = queue.Queue()

async def do_serial():
    reader, writer = await serial_asyncio.open_serial_connection(url='/dev/ttyS0', baudrate=9600)
    while True:
        # read serial port
        data = await reader.readline()

        # echo back to serial port for verification
        writer.write(incoming_serial_queue.get)

        # add data to queue
        incoming_serial_queue.put(data)        

async def main():
    while True:
        # read queued data from serial port
        await print(incoming_serial_queue.get())

asyncio.run(do_serial())
asyncio.run(main())

我不是 asyncio 的专家,但我创建了一些工作代码 - 所以不要问为什么有些东西不起作用:)

我不能 运行 serial_asyncio 所以我用 datetimequeue

生成了一些数据

您不能使用 run() 同时启动两个进程。 run() 启动一个进程并等待它的结束 - 所以 run(do_serial()) 启动函数 do_serial 并等待它的结束 - 这样它永远不会 运行s main。如果您更改顺序,则 run(main()) 将等待 main 结束并且永远不会 运行 do_serial

所以我使用 run() 启动了一个函数,该函数使用 create_task() 用于 do_serial()main()。我必须先创建任务,然后再将它们与 await 一起使用,因为以其他方式它没有启动 main 而且我不知道为什么。

asyncio 的其他问题:await 无法与所有功能一起使用 - 它不适用于标准 print()。您必须为其创建特殊的 print()。或者也许您有来自 serial_asyncio 的特殊 print() - 我不知道。

在这两个函数中,我使用 asyncio.sleep()await

一起使用一些函数

queue 的问题:当队列中没有数据时,get() 可能会阻塞代码,最好先检查它是否不是 empty()

import queue
import asyncio
import datetime

incoming_serial_queue = queue.Queue()

async def do_serial():
    print("do serial")
    while True:
        data = str(datetime.datetime.now())
        print('put:', data)

        # add data to queue
        incoming_serial_queue.put(data)

        await asyncio.sleep(2)

async def main():
    print("main")
    while True:
        # read queued data from serial port
        if not incoming_serial_queue.empty():
            data = incoming_serial_queue.get()
            print('get:', data)

        await asyncio.sleep(1) 

async def start():
    print("start")
    #await do_serial()  # doesn't work
    #await main()       # doesn't work

    # I had to create all tasks before running
    task1 = asyncio.create_task(do_serial())
    task2 = asyncio.create_task(main())

    # running task
    await task1
    await task2

asyncio.run(start())

编辑:

我可以 运行 使用 asyncio.gather()

两个函数
async def start():
    print("start")
    await asyncio.gather(
        do_serial(),
        main(),
    )

其余和我之前的代码一样

import queue
import asyncio
import datetime

incoming_serial_queue = queue.Queue()

async def do_serial():
    print("do serial")
    while True:
        data = str(datetime.datetime.now())
        print('put:', data)

        # add data to queue
        incoming_serial_queue.put(data)

        await asyncio.sleep(2)    

async def main():
    print("main")
    while True:
        # read queued data from serial port
        if not incoming_serial_queue.empty():
            data = incoming_serial_queue.get()
            print('get:', data)

        await asyncio.sleep(1) 

async def start():
    print("start")
    await asyncio.gather(
        do_serial(),
        main(),
    )

asyncio.run(start())