调试时,除了特定错误外,如何中断引发的异常?

While debugging, how can I break on raised exceptions EXCEPT FOR specific errors?

我使用 Visual Studio 代码进行 Python 开发。

一般来说,我希望我的 IDE 在出现异常时中断,所以我在 Debug window:

下选中了 Raised Exceptions 选项

但是,我想忽略一个特定的(与编码相关的)异常,因为它每秒会引发数千次。我将它包装在一个 try-except 块中,但正如预期的那样,它在抛出异常时中断。我想抑制这种行为,但仅限于特定的错误类型。

在 Visual Studio 代码中有没有办法做到这一点?

VScode 中调试时,有几个设置可用于配置 Python 异常行为。对于以下示例,我们假设复选框 Raised ExceptionsUncaught Exceptions 都是 checked(已启用).这通常是调试器因大量不需要的异常而停止的情况。

简介
考虑以下示例。对于此代码,调试器将在指定的三个位置停止。

    try:
        1 / 0                # FIRST STOP
    except:
        pass

    func = lambda: 1 / 0     # SECOND STOP
    try:
        func()               # THIRD STOP
    except:
        pass

请注意,导致上述“第二次停止”的异常不会发生在代码中分配变量 func 的位置。事实上,在 try-except 块之外,这样的代码否则会导致程序退出。相反,当然,异常稍后发生在 嵌套在 延迟调用中,幸运的是 try 保护。这种区别对于下面的示例很重要。

1.行注释
第一种技术允许您防止调试器在代码中的特定位置中断异常。将特殊的 @IgnoreException 标记放在所需行的注释中。有关调试器将识别的此标记的 RegEx 形式,请参阅 here

    try:
        1 / 0                #@IgnoreException
    except:
        pass

    func = lambda: 1 / 0     #@IgnoreException
    try:
        func()               #@IgnoreException
    except:
        pass

这非常适合对调试器停止位置进行专门的、细粒度的控制,但显然作为一种更通用的解决方案,这种方法很快就会失控。不过,在继续之前,请注意有一种方法可以全局启用或禁用调试器中的 @IgnoreException 行为。

此功能在调试器启动时默认启用;如果这就是你所需要的,你可以跳过这一部分。要全局禁用 @IgnoreException 处理,您可以只插入以下代码片段,它在程序开始时执行一次,或者,如果需要,检测您的代码以根据运行时以编程方式启用和禁用 @IgnoreException 处理根据需要的条件。 try-except 块可防止代码在未调试或未安装调试器时崩溃。

    # To enable or disable @IgnoreException handling when pydevd is active:
    #    'True'  - debugger won't stop on '@IgnoreException` lines (default)
    #    'False' - the annotation are ignored, allowing the debugger to stop

    try:
        import pydevd
        d = pydevd.GetGlobalDebugger()
        d.ignore_exceptions_thrown_in_lines_with_ignore_exception = False
    except:
        pass

2。上下文感知忽略
继续第二个选项,我将重置回原始代码,没有行注释。这一次,通过更改秘密调试器开关的值,调试器将仅在调用者的直接上下文之外引发的异常时停止。这是 skip_on_exceptions_thrown_in_same_context 调试器标志,默认情况下 未启用 ,因此如果您想要此行为,则必须显式打开它(如图所示):

    try:
        from pydevd import GetGlobalDebugger
        GetGlobalDebugger().skip_on_exceptions_thrown_in_same_context = True
    except:
        pass

    try:
        1 / 0
    except:
        pass

    func = lambda: 1 / 0
    try:
        func()         # ONLY STOP
    except:
        pass

现在调试器只停止一次,而在第一个示例中,之前出现三个引发的异常时停止。我知道你在想什么,现在结合这两种方法更有意义,因为大多数代码中需要用 @IgnoreException.

注释的点通常会少得多

3。结合这两种技术
所以这是示例的最终版本,即使同时使用 RaisedExceptionsUncaughtExceptions启用选项后,VScode 调试器会一直运行而不会停止:

    try:
        from pydevd import GetGlobalDebugger
        GetGlobalDebugger().skip_on_exceptions_thrown_in_same_context = True
    except: pass

    try:
        1 / 0
    except:
        pass

    func = lambda: 1 / 0
    try:
        func()     #@IgnoreException
    except:
        pass
                   # NO DEBUGGER STOPS...