如何集成Python mido和asyncio?
我有一个通过MIDI进行文件I/O的设备。我有一个使用Mido下载文件的脚本,但它是一堆全局变量。我想整理一下以正确使用asyncio,但我不确定如何集成mido回调。我认为文档中说我应该使用未来的对象,但我不确定mido回调函数如何获得该对象如何集成Python mido和asyncio?,python,python-asyncio,mido,Python,Python Asyncio,Mido,我有一个通过MIDI进行文件I/O的设备。我有一个使用Mido下载文件的脚本,但它是一堆全局变量。我想整理一下以正确使用asyncio,但我不确定如何集成mido回调。我认为文档中说我应该使用未来的对象,但我不确定mido回调函数如何获得该对象 mido提供了一个API,该API将从不同的线程调用回调。回调的实现可以通过调用与asyncio通信。请注意,您不能只设置a的值,因为回调将被调用多次,而future只能设置一次,这意味着只能进行一次性计算 多重调用回调的常见模式是将事件推送到async
mido
提供了一个API,该API将从不同的线程调用回调。回调的实现可以通过调用与asyncio通信。请注意,您不能只设置a的值,因为回调将被调用多次,而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()
make_stream
返回两个对象:
- 一个回调,可以传递给
mido.open\u input()
- 一个流,您可以使用它进行迭代以获取新消息
async for
循环将唤醒一个新项。有效地,make_stream
将线程回调转换为异步迭代器。例如(未经测试):
这正是我一直在寻找的,但无论我是否发送任何MIDI数据,它为我打印的都是无穷无尽的数据流。我知道它未经测试,但我很难找出问题所在。我将
yield queue.get()
更改为yield wait queue.get()
。这就成功了。谢谢@Genoil你说得对queue
是一个异步IO队列,所以它的get()
方法是一个协程,必须等待,duh!顺便问一下,你使用的是什么版本的Python?我们使用的是3.6。10@Genoil谢谢,这就解释了输出是generator object Queue.get的原因,这让我一开始就不感兴趣-asyncio.Queue
被修改为在Python 3.7中使用async def
。您可能需要考虑切换到较新的版本;Python3.7大约在两年前发布。
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)