【发布时间】:2018-07-09 21:07:50
【问题描述】:
我正在尝试在 Python 中实现一个简单的演员系统,以深入了解并发编程。
我主要关心的是使用 asyncio 模块在 Python 中编写期货的通用任务。
假设我有一个在单独的线程上运行的事件循环。
import asyncio
from threading import Thread
loop = asyncio.new_event_loop()
def run_event_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
t = Thread(target=run_event_loop, args=(loop,))
t.start()
为了避免同步通信,我需要能够以某种方式编写Futures。举个简单的例子,假设我想合并两个 async 协程的结果。
我的第一次(显然是错误的)尝试:
async def f(x):
fut = asyncio.run_coroutine_threadsafe(g(x / 2), loop)
return fut
async def g(x):
return x * 2
f(x) = x / 2
g(x) = x * 2
f(g(x)) = x
我无法得出一个干净的解决方案来处理以下一般问题:
x = 10
future = asyncio.run_coroutine_threadsafe(f(x), loop)
print(future) # <Future at 0x106f797f0 state=pending>
print(future.result()) # <Future at 0x10677c780 state=finished returned float>
print(future.result().result()) # 10.0
理想情况下,我应该结合期货并在最后执行一个future.result()。或者,也许我对这一切的思考都错了。
【问题讨论】:
-
您是在询问来自
concurrent.futures的期货,正如您的标题、标签和描述所暗示的那样,还是来自asyncio的期货,正如您的示例代码所暗示的那样?正如文档明确指出的那样,它们不是同一类型。asyncio中的那个模仿了futures中的那个,但它们不能互换使用。 (请注意,有一个asyncio.Executor将并发期货包装在异步期货中;您永远不应该直接在异步代码中使用并发期货。) -
我编辑了标题。
type(future)给了<class 'concurrent.futures._base.Future'>,所以我错误地认为它们是相同的 -
不,这 is 是一个并发的未来,因为您正在使用
run_coroutine_threadsafe并将结果返回到不同的线程中。将两者混合在一起会令人困惑。 -
无论如何,
f是否真的需要像这样运行g线程安全,即使它实际上是在同一线程中的同一事件循环上运行g?如果是这样,您不能直接将生成的并发未来与 asyncio 未来组合在一起,我认为这就是您要解决的问题。如果您不需要它,那么您的问题就会消失。 -
你说得对我只需要做
res = await g(x / 2)
标签: python concurrency python-asyncio