如何集成Python mido和asyncio?

时间:2019-05-23 14:28:17

标签: python python-asyncio mido

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

1 个答案:

答案 0 :(得分:2)

mido提供了一个callback-based API,它将从另一个线程调用回调。您的回调实现可以通过调用loop.call_soon_threadsafe与asyncio通信。请注意,您将无法仅设置Future的值,因为该回调将被多次调用,并且将来只能设置一次-这意味着一次性计算。

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

async 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 queue.get()
    return callback, stream()

make_stream返回两个对象:

  • 回调,您可以将其传递给mido.open_input()
  • 一个流,您可以用async for对其进行迭代以获取新消息

每当Mido在其后台线程中调用回调时,在流中迭代的asyncio async for循环将唤醒一个新项。实际上,make_iter将线程回调转换为异步迭代器。例如(未试用):

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)