我一直在使用asyncio进行并发,但是我遇到了一个问题。我需要使用asyncio安排一个任务,但它是阻塞的,所以我想在一个执行器中使用来自concurrent.futures的threadpool来执行它。
我见过这样的例子,即安排任务:
now = loop.time()
loop.call_at(now + 60, callback, arg, loop)
就像在执行程序中运行任务一样:
blocking_tasks = [
loop.run_in_executor(executor, blocks)
for i in range(6)
]
completed, pending = await asyncio.wait(blocking_tasks)
但是如何安排阻塞任务在执行程序中运行?
答案 0 :(得分:2)
run_in_executor
会返回未来,因此您无法将其与call_at
一起使用,这需要普通的功能。但是,您可以使用asyncio.sleep()
轻松推迟执行:
async def my_task():
await asyncio.sleep(60)
result = await loop.run_in_executor(None, fn)
...
taskobj = loop.create_task(my_task())
这样做的好处是create_task
创建的任务在睡眠期间可以是canceled。此外,您可以从my_task()
返回有用的值,并使用await taskobj
,调用taskobj.result()
或loop.run_until_complete(taskobj)
获取该值。
答案 1 :(得分:0)
我们可以为此创建一个包装器吗?
def run_in_async_loop(f):
@functools.wraps(f)
async def wrapped(*args, **kwargs):
loop = asyncio.get_running_loop()
return (await loop.run_in_executor(None, f(*args, **kwargs))
return wrapped