Python异步事件和串行异步?

2024-06-26 13:58:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我有代码(python类,我称之为Arduino),它将控制数据包写入串行端口(使用serial_asyncio),串行端口用确认数据包进行响应。然而,远程设备也随机向python端发送事件包。我希望该类向实例化我的类的类提供解码的数据包(我将其称为Controller)。我对如何处理这件事感到困惑

我的第一个想法是为Arduino类提供回调:

class Controller:
    def __init__(self):
        self.arduino = Arduino("/dex/ttyS0", self._serialPacketCallback)

    def _serialPacketCallback(self, obj: dict):
        pass # handle spontaneous event packet from remote

但这似乎不是很异步。asyncio的方法是什么?我认为这看起来像:

class Controller:
    def __init__(self):
        self.arduino = Arduino("/dex/ttyS0")

    async readEventPacket(self):
        pass

    #somewhere, not sure where, or how to start it:
    async def _handleEvents(self)
        while True:
            event = await self._readEventPacket()

    async def start(self):
        await self.arduino.start()
        await asyncio.wait([self._handleEvents()])

if __name__ == '__main__':
    controller = Controller()
    loop = asyncio.get_event_loop()
    loop.create_task(controller.start())    
    loop.run_forever()

我环顾四周,看到了使用回调多处理管道附加事件循环的建议,我确信它们是有效的,但我不确定正确的方法是什么。对我来说,我不想启动任何额外的事件循环或线程,这使我认为回调是最好的,但这不是非常异步的,我想知道如何以异步方式进行,而不需要额外的事件循环或回调

我想阐明的另一个问题是,我希望这个类与其他控制器中使用的Arduino类一样松散耦合

旁注:我不确定在Python中何时需要创建新的事件循环

另一个问题:Arduino类如何生成事件并让Controllerawait self._readEventPacket()中拾取它


Tags: 端口selfloopeventasyncioasyncdef事件
1条回答
网友
1楼 · 发布于 2024-06-26 13:58:45

asyncio的好处在于,您始终可以将基于回调的接口转换为基于协同路由的接口,反之亦然

假设Arduino类实现了一个基于回调的接口,如下所示(未测试):

class Arduino:
    def __init__(self, device, callback):
        self._device = device
        self._callback = callback

    async def start(self):
        reader, writer = await serial_asyncio.connect(url=self._device, baudrate=115200)
        while True:
            data = await reader.read(1024)
            self._callback(data)

您可以使用队列将该接口转换为基于协同路由的接口:

def callback_to_coro():
    # Return two functions, one that can be passed as callback to
    # code that expects it, and the other a coroutine that can be
    # awaited to get the values the callback was invoked with.
    queue = asyncio.Queue()
    return queue.put_nowait, queue.get

使用该代码,您可以实现如下Controller.read_event_packet

class Controller:
    def __init__(self):
        callback, wait = callback_to_coro()
        self.arduino = Arduino("/dex/ttyS0", callback)
        self.read_event_packet = wait

相关问题 更多 >