首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在异步中找出CancelledError的原因?

如何在异步中找出CancelledError的原因?
EN

Stack Overflow用户
提问于 2022-03-02 15:03:26
回答 2查看 975关注 0票数 0

我有一个大型项目,它依赖于一些第三方库,有时它的执行会被CancelledError中断。

为了演示这个问题,让我们看一个小例子:

代码语言:javascript
运行
复制
import asyncio


async def main():
    task = asyncio.create_task(foo())

    # Cancel the task in 1 second.
    loop = asyncio.get_event_loop()
    loop.call_later(1.0, lambda: task.cancel())

    await task


async def foo():
    await asyncio.sleep(999)


if __name__ == '__main__':
    asyncio.run(main())

回溯:

代码语言:javascript
运行
复制
Traceback (most recent call last):
  File "/Users/ss/Library/Application Support/JetBrains/PyCharm2021.2/scratches/async.py", line 19, in <module>
    asyncio.run(main())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
    return future.result()
concurrent.futures._base.CancelledError

如您所见,没有关于CancelledError的发源地的任何信息。我该怎么找出原因呢?

我想出的一种方法是放置大量的试/除块,这将捕获CancelledError并缩小它的来源。但这很乏味。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-03-04 19:42:40

我通过在项目中的每个异步函数中应用一个装饰器来解决这个问题。当从函数引发CancelledError时,装饰者的工作很简单-记录一条消息。这样,我们将看到哪些函数(更重要的是,按哪个顺序)被取消。

下面是装饰代码:

代码语言:javascript
运行
复制
def log_cancellation(f):
    async def wrapper(*args, **kwargs):
        try:
            return await f(*args, **kwargs)
        except asyncio.CancelledError:
            print(f"Cancelled {f}")
            raise
    return wrapper

为了在任何地方添加这个装饰器,我使用regex。查找:(.*)(async def).替换为:$1@log_cancellation\n$1$2

另外,为了避免在每个文件中导入log_cancellation,我修改了builtins:builtins.log_cancellation = log_cancellation

票数 0
EN

Stack Overflow用户

发布于 2022-11-17 12:23:03

rich包帮助我们识别了CancelledError的原因,而无需进行太多的代码更改。

代码语言:javascript
运行
复制
from rich.console import Console

console = Console()

if __name__ == "__main__":
    try:
        asyncio.run(main())  # replace main() with your entrypoint
    except BaseException as e:
        console.print_exception(show_locals=True)
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71324885

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档