我有以下一段 Python 异步代码。
import asyncio
async def get_some_values_from_io():
print("Getsome value Executing...")
await asyncio.sleep(3)
return [100,200]
vals = []
async def fetcher():
while True:
print("Fetcher Executing...")
io_vals = await get_some_values_from_io()
for val in io_vals:
vals.append(io_vals)
async def monitor():
while True:
print("Monitor Executing...")
print (len(vals))
await asyncio.sleep(3)
async def main():
t1 = asyncio.create_task(fetcher())
t2 = asyncio.create_task(monitor())
await asyncio.gather(t1, t2)
asyncio.run(main())
print("Rest of the method is executing....")
被调用的两个异步函数都调用 async.sleep() 方法,并有相当长的睡眠时间。 当它们都睡眠时,必须运行最后一个打印语句
print("Rest of the method is executing....")
。
但是打印出来的是:(事实上它一直在继续)
Fetcher Executing...
Getsome value Executing...
Monitor Executing...
0
Fetcher Executing...
Getsome value Executing...
Monitor Executing...
2
...
我的理解是,整个Python程序只是单线程(GIL),事件循环也会共享GIL。是不是不正确?
此外,还提到了 run_in_executor() 方法,该方法表示 CPU 密集型任务可以在事件循环之外使用此方法运行。那么这意味着,除了事件循环之外,还有另一个线程并行运行?这与 GIL 的事实相矛盾。
异步不会创建新线程。基本上所有异步作业都在当前线程中执行。所以你的
async
任务正在主线程中运行,应该写 Rest of the method is executing
。如您所知,单线程只能执行三项工作之一:1)执行 asynctask #1 2)执行 asynctask #2 3)执行其余代码。
但是,当您调用
asyncio.run
时,该函数会同时执行这两个任务,并且默认情况下会等待这两个任务完成。因此它无法切换到最后一行。
要修复此行为,您需要创建第二个线程并在第二个线程中使用
run_coroutine_threadsafe
运行协程。