拨打asyncio.sleep(0) 3次:
import asyncio
import time
async def light_job():
print("hello ")
print(time.time())
await asyncio.sleep(1)
print(time.time())
print("world!")
async def heavy_job():
print("heavy start")
time.sleep(3)
print("heavy halt started")
for _ in range(3):
await asyncio.sleep(0)
print("heavy halt ended")
time.sleep(3)
print("heavy done")
async def test():
await asyncio.gather(
light_job(),
heavy_job()
)
asyncio.run(test())
这导致:
hello
1668844526.157173
heavy start
heavy halt started
1668844529.1575627
world!
heavy halt ended
heavy done
查看“asyncio/base_events.py”,“_run_once”首先遍历挂起的计时器,然后在计算之后运行它看到的所有内容。 asyncio.sleep 只能跳过事件循环的一次迭代。需要多次睡眠,因为 asyncio.sleep(1) 安排了一个未来,在通过将 light_job 添加回队列将控制权交还给 light_job 之前,需要进行一次额外的迭代,而 asyncio 恰好最后运行新排队的作业。
为了更清晰的图片,可以添加更多的打印语句:
import asyncio
import time
async def light_job():
print("hello ")
print(time.time())
await asyncio.sleep(1)
print(time.time())
print("world!")
async def heavy_job():
print("heavy start")
time.sleep(3)
print("heavy halt started")
# Sleep to yield to the event loop. light_job isn't detected as ready so this iteration of the loop will finish
await asyncio.sleep(0)
print("after 1 sleep")
# We are still in front of the event loop. Yield so that the 1 second timer in light_job runs.
# The timer will realize it itself has expired, then put light_job back onto the queue.
await asyncio.sleep(0)
# Again the current Python implementation puts us in front. Yield so that the light_job runs
print("after 2 sleeps")
await asyncio.sleep(0)
print("heavy halt ended")
time.sleep(3)
print("heavy done")
async def test():
await asyncio.gather(
light_job(),
heavy_job()
)
asyncio.run(test())
然后在“asyncio/base_events.py”的“def _run_once(self):”中添加断点。在第 1842 行的开头添加断点打印“loop start”,也就是“sched_count =”。在末尾的第 1910 行添加另一个,也就是“handle = None”打印“loop end”。然后在第 1897 行运行每个任务之前添加一个,也就是“if self._debug:”评估和打印“_format_handle(handle)”。事件的顺序被揭示:
loop start
<Task pending name='Task-1' coro=<test() running at /home/home/PycharmProjects/sandbox/notsync.py:34> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Task pending name='Task-2' coro=<light_job() running at /home/home/PycharmProjects/sandbox/notsync.py:5> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
hello
1668844827.5052986
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:13> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
heavy start
heavy halt started
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:18> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
after 1 sleep
<TimerHandle when=37442.097934711 _set_result_unless_cancelled(<Future pendi...ask_wakeup()]>, None) at /usr/lib/python3.11/asyncio/futures.py:317>
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:23> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
after 2 sleeps
<Task pending name='Task-2' coro=<light_job() running at /home/home/PycharmProjects/sandbox/notsync.py:8> wait_for=<Future finished result=None> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
1668844830.9250844
world!
loop end
loop start
<Task pending name='Task-3' coro=<heavy_job() running at /home/home/PycharmProjects/sandbox/notsync.py:27> cb=[gather.<locals>._done_callback() at /usr/lib/python3.11/asyncio/tasks.py:759]>
heavy halt ended
heavy done
<Handle gather.<locals>._done_callback(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/tasks.py:759>
loop end
loop start
<Handle gather.<locals>._done_callback(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/tasks.py:759>
loop end
loop start
<Task pending name='Task-1' coro=<test() running at /home/home/PycharmProjects/sandbox/notsync.py:35> wait_for=<_GatheringFuture finished result=[None, None]> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end
loop start
<Task pending name='Task-4' coro=<BaseEventLoop.shutdown_asyncgens() running at /usr/lib/python3.11/asyncio/base_events.py:539> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end
loop start
<Task pending name='Task-5' coro=<BaseEventLoop.shutdown_default_executor() running at /usr/lib/python3.11/asyncio/base_events.py:564> cb=[_run_until_complete_cb() at /usr/lib/python3.11/asyncio/base_events.py:180]>
loop end
loop start
<Handle _run_until_complete_cb(<Task finishe...> result=None>) at /usr/lib/python3.11/asyncio/base_events.py:180>
loop end