代码之家  ›  专栏  ›  技术社区  ›  Aaron_ab

concurrent.futures.future能否转换为asyncio.future?

  •  3
  • Aaron_ab  · 技术社区  · 5 年前

    我在练习 asyncio 在写了很多年的多线程代码之后。

    注意到一些我觉得奇怪的事情。两者都在 阿辛乔 而在 concurrent 有一个 Future 对象。

    from asyncio import Future
    from concurrent.futures import Future
    

    猜猜每个人都有自己的角色……

    我的问题是我能否转车 concurrent.future.Future asyncio.Future (或相反)?

    2 回复  |  直到 5 年前
        1
  •  2
  •   Mikhail Gerasimov    5 年前

    concurrent.futures.Future 是一个我们用来写基于OS线程或OS进程以及其他东西的异步代码的对象 concurrent.futures 模块为我们提供了。

    asyncio.Future 是一个我们用来基于协程和事物编写异步代码的对象 asyncio 模块为我们提供了。

    换言之 同期期货 阿辛乔 试着用不同的方法解决相同的任务。解决相同的任务意味着许多事情在基于线程/流程的方法和基于协程的方法中是相似的。例如,看看 asyncio.Lock threading.Lock -相似,但不同。

    不同的类似物体之间的转换是可能的吗?不,不是。

    两者的本质区别 阿辛乔 基于线程的模块使得合作无法:

    • 在Asyncio中,您应该 await 暂停执行流并允许同时执行其他协同程序的操作。

    • 在基于线程的模块中,通过挂起整个线程来挂起执行流。

    例如,当您编写基于线程的代码时,您会编写:

    future = concurrent.futures.Future()
    # ...
    result = future.result()  # acts like time.sleep blocking whole thread
    

    但在Asyncio中,不应阻塞线程,应将控件返回到事件循环:

    future = asyncio.Future()
    # ...
    result = await future  # block current execution flow returning control to event loop 
                           # without blocking thread,
                           # current flow will be resumed later
    
        2
  •  1
  •   user4815162342    5 年前

    我的问题是我能否转车 concurrent.future.Future asyncio.Future (或相反)?

    如果说“转移”,你的意思是“把一个转换成另一个”,是的,这是可能的,尽管在方法之间的阻抗失配桥接可能需要一些工作。

    转换一个 concurrent.futures.Future 变成一个 未来的未来 你可以打电话 asyncio.wrap_future .返回的asyncio future在asyncio事件循环中等待,并将在基础线程future完成时完成。这是如何有效地 run_in_executor 实现。

    没有公共功能可以将Asyncio Future直接转换为 concurrent.futures 未来,但有 asyncio.run_coroutine_threadsafe 函数,它需要 协同程序 ,将其提交到事件循环,并返回在Asyncio Future完成时完成的并发Future。这可以用来有效地将任何可等待的异步未来转换为并发未来,如下所示:

    def to_concurrent(fut, loop):
        async def wait():
            await fut
        return asyncio.run_coroutine_threadsafe(wait(), loop)
    

    返回的未来将表现得像您对并发未来的预期,例如 result() 方法将阻塞等。您可能需要注意的一件事是,回调使用 add_done_callback (一如既往)在完成未来的线程中运行,在本例中是事件循环线程。这意味着,如果添加完成的回调,则需要注意不要在实现中调用阻塞调用,以免阻塞事件循环。