Python 中 future/promise(线程)的等价物是什么?

问题描述 投票:0回答:2

我来自 C++ 世界,我正在寻找 Python 中 std::future、std::promise 的等价物。 Python 中是否有等效的机制或其他方法来实现相同的目的? 我知道 asyncio.Future,但我需要它用于线程而不是 asyncio。

我正在使用第三方库(PJSUA2),我直接从主线程调用它,但它在库创建的工作线程的上下文中以异步回调形式发送结果。

期待 Python 中的 future/promise 支持,我希望像这样编写我的应用程序代码:

future = wrap_foo(...)
if (future.get() != expected_result):
  throw Exception(...)

future1 = wrap_foo(...)
future2 = wrap_bar(...)

我计划使用 wrap_xxx 函数(其中库函数称为 xxx)包装所有库异步调用,负责创建 future/promise 对象。

我需要有多个 future 挂起的能力,所以我不能简单地创建同步 wrap_xxx 函数,这些函数会阻塞直到结果准备好。

python multithreading promise future
2个回答
1
投票

参见 asyncio 模块 -

import asyncio

async def main():
    print('hello')
    await asyncio.sleep(1)
    print('world')

asyncio.run(main())
hello
world

它支持协程 -

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())
started at 17:13:52
hello
world
finished at 17:13:55

任务 -

import asyncio

async def nested():
    return 42

async def main():
    # Schedule nested() to run soon concurrently
    # with "main()".
    task = asyncio.create_task(nested())

    # "task" can now be used to cancel "nested()", or
    # can simply be awaited to wait until it is complete:
    print(await task)

asyncio.run(main())
42

期货 -

import asyncio

async def set_after(fut, delay, value):
    # Sleep for *delay* seconds.
    await asyncio.sleep(delay)

    # Set *value* as a result of *fut* Future.
    fut.set_result(value)

async def main():
    # Get the current event loop.
    loop = asyncio.get_running_loop()

    # Create a new Future object.
    fut = loop.create_future()

    # Run "set_after()" coroutine in a parallel Task.
    # We are using the low-level "loop.create_task()" API here because
    # we already have a reference to the event loop at hand.
    # Otherwise we could have just used "asyncio.create_task()".
    loop.create_task(
        set_after(fut, 1, '... world'))

    print('hello ...')

    # Wait until *fut* has a result (1 second) and print it.
    print(await fut)

asyncio.run(main())
hello ...
... world

0
投票

C++ std::async 库与 python Asyncio 不同。与在单个线程上使用事件循环的 Asyncio 不同,C++ 异步库在单个线程上启动每个任务(除非传递 std::launch::deferred 参数)。因此,asyncio 中任务之间的通信不是在不同线程上运行的多个任务之间,而是在同一线程上运行的多个任务之间。

不幸的是,Python 目前不提供与 C++ 中的 std::future 库相同的通信。不过,有一些既定的做法:

  1. 通过引用变量传递进行线程间通信 - 使用队列库中的队列,因为它是线程安全的。

使用 python 线程的 GUI 应用程序如下所示:

线程 1 检查队列中的命令并更新 GUI。

线程 2(3、4、5...)响应用户 GUI 交互,完成它们必须做的任何工作,完成后将其结果推送到队列。

线程 1 然后更新用户的 GUI。

附注由于在 Python 上,在任何给定时间只有一个线程在运行(调度程序非常频繁地交换运行的线程,因此 GUI 应用程序、I/O 都可以,但没有真正的线程并行性),因此使用线程和 asyncio(在一个线程上运行的事件循环)线程(这意味着您无法获得并行性的好处,但不会阻塞 I/O 操作),这对于性能密集型操作不利,并且不会获得任何速度优势。如果需要并行性,应该使用 Multiprocessing 库。

© www.soinside.com 2019 - 2024. All rights reserved.