我正在尝试用Python实现一个简单的参与者系统,以获得有关并发编程的一些见解。
我主要关注的是使用asyncio
模块在Python语言中组合期货的通用任务。
假设我有一个事件循环在单独的Thread上运行。
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()
。也许我对这一切的思考都是错误的。
发布于 2018-07-10 05:42:29
这里的根本问题是:
fut = asyncio.run_coroutine_threadsafe(g(x / 2), loop)
您在一个async
函数中,并试图在同一线程中的同一事件循环中运行另一个异步函数。为此,您不需要run_coroutine_threadsafe
;只需await
它。
如果你调用run_coroutine_threadsafe
会发生什么呢?那么你得到的是一个concurrent.futures.Future
。正如asyncio
文档顶部所解释的,这与asnycio.Future
-which旨在模拟并发未来不是一回事,但在幕后却是另一回事。你可以组合两个异步期货(来自同一个事件循环),你可以组合两个并发的未来,但你不能组合一个异步的未来。
您可以在异步未来中包装并发的未来(直接使用wrap_future
,或者更常见的是,通过run_in_executor
间接)。但是,你最终会得到一个并发的未来,持有一个异步的未来,包装一个并发的未来,这仍然不能被组合。
https://stackoverflow.com/questions/51254050
复制相似问题