如何集成 Python mido 和 asyncio?

Mar*_*een 5 python python-asyncio mido

我有一个通过 MIDI 执行文件 I/O 的设备。我有一个使用 Mido 下载文件的脚本,但它是一堆全局变量。我想整理一下以正确使用 asyncio,但我不确定如何集成 mido 回调。我认为文档说我应该使用 Future 对象,但我不确定 mido 回调函数如何获取该对象。

use*_*342 6

mido提供了一个基于回调的API,它将从不同的线程调用回调。您的回调实现可以通过调用loop.call_soon_threadsafe. 请注意,您不能只设置 a 的值,Future因为回调将被多次调用,并且只能设置一次 future - 它用于一次性计算。

多次调用回调的常见模式是将事件推送到 asyncio队列并在 asyncio 代码中从中弹出内容。通过将队列公开为异步迭代器,这可以变得更加方便。此功能使过程自动化:

def make_stream():
    loop = asyncio.get_event_loop()
    queue = asyncio.Queue()
    def callback(message):
        loop.call_soon_threadsafe(queue.put_nowait, message)
    async def stream():
        while True:
            yield await queue.get()
    return callback, stream()
Run Code Online (Sandbox Code Playgroud)

make_stream 返回两个对象:

  • 一个回调,你可以传递给mido.open_input()
  • 一个流,您可以迭代它async for以获取新消息

每当 mido 在其后台线程中调用回调时,async for迭代流的异步循环将唤醒一个新项目。有效地make_stream将线程回调转换为异步迭代器。例如(未经测试):

async def print_messages():
    # create a callback/stream pair and pass callback to mido
    cb, stream = make_stream()
    mido.open_input(callback=cb)

    # print messages as they come just by reading from stream
    async for message in stream:
        print(message)
Run Code Online (Sandbox Code Playgroud)