mido
provides a callback-based API which will invoke the callback from a different thread.
(mido
提供了一个基于回调的 API,该API将从另一个线程中调用该回调。)
Your implementation of the callback can communicate with asyncio by calling loop.call_soon_threadsafe
. (您的回调实现可以通过调用loop.call_soon_threadsafe
与asyncio通信。)
Note that you won't be able to just set the value of a Future
because the callback will be called multiple times, and a future can only be set once - it is meant for one-shot computations. (请注意,您将无法仅设置Future
的值,因为回调将被多次调用,并且Future
只能设置一次-这意味着一次性计算。)
A common pattern for multiply invoked callbacks is to push events onto an asyncio queue and pop stuff from it in asyncio code.
(多次调用回调的常见模式是将事件推送到异步队列,并以异步代码从中弹出内容。)
This can be made even more convenient by exposing the queue as an async iterator. (通过将队列公开为异步迭代器,可以更加方便。)
This function automates the process: (此功能使过程自动化:)
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
returns two objects:
(make_stream
返回两个对象:)
Whenever the callback is invoked by mido in its background thread, your asyncio async for
loop iterating over the stream will wake up with a new item.
(每当mido在其后台线程中调用该回调时,在流上循环的asyncio async for
循环迭代都会唤醒一个新项。)
Effectively, make_stream
converts a threaded callback into an async iterator. (有效地, make_stream
将线程回调转换为异步迭代器。)
For example (untested): (例如(未测试):)
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)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…