Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
255 views
in Technique[技术] by (71.8m points)

python - 如何集成Python mido和asyncio?(How can I integrate Python mido and asyncio?)

I have a device which does file I/O over MIDI.

(我有一台可以通过MIDI文件进行I / O的设备。)

I have a script using Mido that downloads files but it is a mess of global variables.

(我有一个使用Mido的脚本,该脚本可以下载文件,但这是一堆全局变量。)

I want to tidy it up to use asyncio properly but I am not sure how to integrate the mido callback.

(我想整理一下以正确使用asyncio,但是我不确定如何集成mido回调。)

I think the documentation says I should use a Future object but I am not sure how the mido callback function can obtain that object.

(我认为文档说我应该使用Future对象,但是我不确定mido回调函数如何获取该对象。)

  ask by Mark Green translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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返回两个对象:)

  • a callback , which you can pass to mido.open_input()

    (一个回调 ,您可以将其传递给mido.open_input())

  • a stream, which you can iterate with async for to get new messages

    (一个流,您可以使用async for迭代以获取新消息)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...