我无法弄清楚这种行为。我使用的是 Python 3.6.4。
在这里,我有 4 个异步函数。在 test1
中,我调用 asyncio.ensure_future(TestAsync())
并将协程转换为任务。在其他(test2
、test3
、test4
)上,我没有调用ensure_future()
,我只是创建了协程并将它们传递到一个列表中,然后将该列表传递到事件循环中。
我将 test1
排除在传递到事件循环的列表之外。所以我的印象是 test1 不会运行,但在我的输出中,它显然运行了。有人可以向我解释为什么 test1
不在事件循环内时仍然输出吗?
import asyncio
import random
async def TestAsync():
print("Test 1 started")
wait = random.randint(1, 10)
await asyncio.sleep(wait)
print("Test 1 done awaited: " + str(wait))
async def TestAsync2():
print("Test 2 started")
wait = random.randint(1, 10)
await asyncio.sleep(wait)
print("Test 2 done awaited: " + str(wait))
async def TestAsync3():
print("Test 3 started")
wait = random.randint(1, 10)
await asyncio.sleep(wait)
print("Test 3 done awaited: " + str(wait))
async def TestAsync4():
print("Test 4 started")
wait = random.randint(1, 10)
await asyncio.sleep(wait)
print("Test 4 done awaited: " + str(wait))
test1 = asyncio.ensure_future(TestAsync())
test2 = TestAsync2()
test3 = TestAsync3()
test4 = TestAsync4()
tasklist = [test2, test3, test4]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasklist))
输出
Test 1 started. <--This is the one wasn't in the event loop
Test 3 started
Test 4 started
Test 2 started
Test 4 done awaited: 1
Test 3 done awaited: 2
Test 1 done awaited: 7
Test 2 done awaited: 10
最佳答案
正如其他人指出的那样,ensure_future
会将任务添加到默认事件循环中,以便在下一次机会时运行。 ensure_future
将任意可等待转换为 asyncio.Future
,在协程对象的情况下,这是通过将其包装到 Task
中来完成的。 (Future
的子类),具有 call到create_task
。无论调用 ensure_future
的代码是否存储对返回的 future 的引用,该任务都将在下次事件循环旋转时运行。
另一个需要注意的重要事项是 run_until_complete(x)
表示“将 x
提交到事件循环并运行循环直到 x
Completes”,它不会阻止在调用 run_until_complete
之前添加的任务运行。
在Python 3.7中,有一个新函数asyncio.run
创建一个新的事件循环并向其提交给定的协程。将 asyncio.run_until_complete
替换为 asyncio.run
将产生您期望的行为。
关于python - 不确定为什么异步任务在事件循环之外完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52251325/