如果我取消注释第一个示例的行,我只会得到一个运行时警告,如下所示:
C:\Users\marat\AppData\Local\Programs\Python\Python312\Lib\asyncio\events.py:88: RuntimeWarning: coroutine 'some_async_func' was never awaited
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
如果我取消注释第二个示例的行,我会收到四个具有相同文本的运行时警告。
为什么在第一个例子中我只收到一个警告,而在第二个例子中,如果在这两种情况下我创建了四个协程?
,我会收到四个警告import asyncio
async def some_async_func():
await asyncio.sleep(1)
async def main() -> None:
pass
# FIRST EXAMPLE.
# coros = [some_async_func() for _ in range(4)] # If i uncommment this i get ONE warning
# SECOND EXAMPLE
# z = some_async_func() # If i uncommment these 4 lines, i get FOUR warnings
# z = some_async_func()
# z = some_async_func()
# z = some_async_func()
if __name__ == '__main__':
asyncio.run(main())
此外,如果我取消注释两个示例,我会收到四个警告,不是五个。
python版本:3.12.8
默认警告模式是“一次”——这意味着它只会对特定调用站点发出一次警告
在理解中,您有一个调用站点(被多次调用)
在非理解版本中,您有四个单独的调用点,因此您会收到四个(实际上是 3 个,见下文)单独的警告
“关闭一”的怪癖是由于警告的引发方式造成的——只有当协程的引用计数降到零时才会引发警告(没有等待)——如果您在之后添加
z = None
你的代码或多或少会得到你所期望的(较长的答案与 python 进程如何被拆除以及最后一个分配何时被垃圾收集有关)
请注意,根据 python 版本,输出有点令人困惑,因为每个协程还会收到两个警告(因为系统建议您使用
tracemalloc
来找出原始调用者):
$ python t.py
C:\Users\asott\t.py:16: RuntimeWarning: coroutine 'some_async_func' was never awaited
z = some_async_func()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
C:\Users\asott\t.py:17: RuntimeWarning: coroutine 'some_async_func' was never awaited
z = some_async_func()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
C:\Users\asott\t.py:18: RuntimeWarning: coroutine 'some_async_func' was never awaited
z = some_async_func()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
C:\Python312\Lib\asyncio\events.py:88: RuntimeWarning: coroutine 'some_async_func' was never awaited
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback