gpt4 book ai didi

python - 为什么 `asyncio.run()` 在 Python 3.8 中永远不会返回?

转载 作者:行者123 更新时间:2023-12-01 12:02:58 27 4
gpt4 key购买 nike

我的应用程序具有以下顶级代码(略有缩写):

def main():
# Some setup code ...
try:
asyncio.run(my_coroutine())
except Exception as e:
print("Exiting due to exception {}: {}".format(type(e).__name__, e))
print("Coroutine finished")
# Some cleanup code ...
print("Shutdown complete")

在 Python 3.8 中 asyncio.run永远不会完成,因此清理代码不会运行(并且不会打印关闭文本)。当应用程序应该退出时,它只是永远挂起。在 Python 3.7 中它运行良好。 Python 3.6 没有 asyncio.run , 但与 loop.run_until_complete() 的代码相当相似和 loop.close()也工作了。

一些额外的上下文:设置和清理代码启动并优雅地退出由 threading.Thread 创建的工作线程。 .正是这个线程实际上停止了主协程:它使用 my_coroutine() 取消了协程(从技术上讲,它取消了在 loop.call_soon_threadsafe 中调用的另一个协程)

最佳答案

问题的前提是错误的。 (我知道是在我写的时候而不是在我最初遇到问题的时候,所以我把它留在这个表格给其他有同样问题的人。)asyncio.run()正在完成,但跳过所有异常处理和关闭代码:

def main():
# Some setup code ...
try:
asyncio.run(my_coroutine())
except Exception as e:
# <---- In Python 3.7, control passed to here when asyncio.run() finshed
print("Exiting due to exception {}: {}".format(type(e).__name__, e))
print("Coroutine finished")
# Some cleanup code ...
print("Shutdown complete")
# <---- In Python 3.8 it directly dropped out of here!

这是因为,在 Python 3.8 中, asyncio.CancelledError 的基类原为 ExceptionBaseException (这是 Exception 的基类)。这样做是为了避免人们在异步代码中发现错误 Exception认为这意味着某些操作失败(例如网络错误)但意外阻止了取消;见 Python issue 32528 .

然后应用程序无法退出,因为 Python 等待所有线程完成,除非它们以 daemon=False 启动。传递给 Thread构造函数(参见 Thread objects docs 的几段讨论)。在我的情况下,该线程不是守护线程(因为我确实希望它优雅地完成)但除非我要求它,否则它不会退出,这是在代码中完成的,我在其中添加了注释“一些清理代码...... ”。

解决办法是要么抓 asyncio.CancelledError明确除了 Exception ,或使用 finally:块代替。 finally: block 可能更好,因为它确实保证代码将运行,即使面对源自 BaseException 的其他异常也是如此。如 KeyboardInterrupt :
def main():
# Some setup code ...
try:
asyncio.run(my_coroutine())
finally:
print("Coroutine finished")
# Some cleanup code ...
print("Shutdown complete")

关于python - 为什么 `asyncio.run()` 在 Python 3.8 中永远不会返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60167683/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com