如何在 python 中使用 asyncio 按下和释放?

How to press and release using asyncio in python?

我想用 python 为强化学习环境制作键盘管理器。我在 time.sleep() 与环境

同步时遇到一些问题

这就是我想要的:

import asyncio
from pynput.keyboard import Key, Controller

class KeyboardManager:
    def __init__(self):
        self.keyboard = Controller()

    def release(self):
        self.keyboard.release(Key.left)
        self.keyboard.release(Key.right)

    async def press_right(self, press_time): 
        self.keyboard.press(Key.right)
        await asyncio.sleep(press_time)
        self.keyboard.release(Key.right)

并将此 class 与另一个脚本一起使用

class Env:
    def action_right(self):
        self.keyboard_manager.press_right(10)

此代码无效。
我想我必须在某个地方听 asyncio 循环。
有什么好主意吗? 请帮助

async 标记 press_right 函数后,将其 return 值转换为必须在某处等待的协程。 您可以通过以下方式将 异步性 传播到 Env.action_right

class Env:
    async def action_right(self):
        await self.keyboard_manager.press_right(10)

但在某些时候,您将不得不等待您的异步代码。例如,您可以使用 loop.run_until_complete():

自己处理异步事件循环
from asyncio import get_event_loop

class Env:
    def __init__(self, ...):
        ...
        self.loop = get_event_loop()

    def action_right(self):
        loop.run_until_complete(self.keyboard_manager.press_right(10))

如果您使用的是 Python 3.7,您可以:

import asyncio

class Env:
    def action_right(self):
        asyncio.run(self.keyboard_manager.press_right(10))

无论如何,我猜你不想在那个时候等待你的异步代码,因为在那种情况下我看不出让 KeywordManager.press_right 异步的意义。

如果您的框架打算与异步代码一起使用,事件循环可能由框架处理,您只需要传播您的异步代码(例如 aiohttp 服务器的情况)。相反,如果您使用的是 RL 库 gym,您将无法获得此类功能,而且我认为使用一些异步代码不会有太大帮助。