Python 事件循环中的意外行为

问题描述 投票:0回答:1

我有以下一段 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 的事实相矛盾。

python python-asyncio event-loop
1个回答
0
投票

异步不会创建新线程。基本上所有异步作业都在当前线程中执行。所以你的

async
任务正在主线程中运行,应该写
Rest of the method is executing
。如您所知,单线程只能执行三项工作之一:1)执行 asynctask #1 2)执行 asynctask #2 3)执行其余代码。

但是,当您调用

asyncio.run
时,该函数会同时执行这两个任务,并且默认情况下会等待这两个任务完成。因此它无法切换到最后一行。

要修复此行为,您需要创建第二个线程并在第二个线程中使用

run_coroutine_threadsafe
运行协程。

© www.soinside.com 2019 - 2024. All rights reserved.