将asyncio与外部库中的非异步回调方法一起使用

2024-09-27 00:15:37 发布

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

我使用gpiozeropython库来处理Raspberry Pi上的简单GPIO设备(我在这里使用MotionSensor作为示例):

import asyncio
from gpiozero import MotionSensor


class MotionSensorHandler():
    __whenMotionCallback = None

    def __init__(self, pin, whenMotionCallback):
        # whenMotionCallback is an async function
        self.__whenMotionCallback = whenMotionCallback

        # Just init the sensor with gpiozero lib
        motionSensor = MotionSensor(pin)

        # Method to call when motion is detected
        motionSensor.when_motion = self.whenMotion

    async def whenMotion(self):
        await self.__whenMotionCallback()

我在这里的问题是,我试图给一个async函数提供对motionSensor.when_motion的回调。你知道吗

所以我得到的错误是whenMotion函数是async,但从来没有await,但我实际上不能等待它:

# will not work because MotionSensor() is not using asyncio
motionSensor.when_motion = await self.whenMotion

你知道我怎么把我的async函数分配给一个none函数吗?你知道吗


Tags: 函数importselfasyncioasyncisdefawait
3条回答

所以经过研究,我发现我必须创建一个新的asyncio循环,以非异步方法执行异步脚本。所以现在我的whenMotion()方法不再是async,而是使用ensure_future()执行一个。你知道吗

import asyncio
from gpiozero import MotionSensor


class MotionSensorHandler():
    __whenMotionCallback = None

    def __init__(self, pin, whenMotionCallback):
        # whenMotionCallback is an async function
        self.__whenMotionCallback = whenMotionCallback

        # Just init the sensor with gpiozero lib
        motionSensor = MotionSensor(pin)

        # Method to call when motion is detected
        motionSensor.when_motion = self.whenMotion

    def whenMotion(self):
        # Create new asyncio loop
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        future = asyncio.ensure_future(self.__executeWhenMotionCallback()) # Execute async method
        loop.run_until_complete(future)
        loop.close()

    async def __executeWhenMotionCallback(self):
        await self.__whenMotionCallback()

假设这是在循环中运行的,when_motion不需要返回值,您可以执行以下操作:

        ...
        motionSensor.when_motion = self.whenMotion

    def whenMotion(self):
        asyncio.ensure_future(self.__whenMotionCallback())

这将在事件循环中调度异步回调,并保持库的调用代码同步。你知道吗

如果您使用协同程序执行此操作,则需要获取并运行事件循环。我假设您使用的是python 3.7,在这种情况下,您可以执行以下操作:

import asyncio
from gpiozero import MotionSensor


class MotionSensorHandler():
    __whenMotionCallback = None

    def __init__(self, pin, whenMotionCallback):
        # whenMotionCallback is an async function
        self.__whenMotionCallback = whenMotionCallback

        # Just init the sensor with gpiozero lib
        motionSensor = MotionSensor(pin)

        # Method to call when motion is detected
        loop = asyncio.get_event_loop()
        motionSensor.when_motion = loop.run_until_complete(self.whenMotion())
        loop.close()

    async def whenMotion(self):
        await self.__whenMotionCallback()

如果您使用的是python3.8,那么只需使用asyncio.run,而不是所有显式获取和运行事件循环的函数。你知道吗

相关问题 更多 >

    热门问题