Answer a question

I use Visual Studio Code for Python development.

In general, I want my IDE to break whenever an exception is raised, so I have the Raised Exceptions option checked under the Debug window:

enter image description here

However, there is a specific (encoding-related) exception I would like to ignore because it is raised thousands of times per second. I wrap it in a try-except blocks but, as expected, it breaks when the exception is thrown. I want to suppress this behavior but only for a specific error type.

Is there a way to do this in Visual Studio Code?

Answers

There are a couple settings available for configuring Python exception behavior when debugging in VScode. For the following examples, we assume that the checkboxes Raised Exceptions and Uncaught Exceptions are both checked (enabled). This is normally a situation where there the debugger is stopping for lots of unwanted exceptions.

Intro
Consider the following example. For this code, the debugger will stop at the three places indicated.

    try:
        1 / 0                # FIRST STOP
    except:
        pass

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

Note that the exception that causes the "second stop" notated above doesn't occur at the point in the code where variable func is assigned. Indeed, being outside of a try-except block, such code would otherwise cause the program to exit. Instead, of course, the exception happens later on nested within the delayed invocation, which thankfully is protected by try. This distinction will become important for an example further below.

1. Line annotation
The first technique allows you to prevent the debugger from breaking on exceptions at specific locations in your code. Put the special @IgnoreException token in a comment on the desired line or lines. See here for the RegEx forms of this tag which the debugger will recognize.

    try:
        1 / 0                #@IgnoreException
    except:
        pass

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

This is great for specialized, fine-grained control of where the debugger stops, but obviously as a more general solution, this approach will quickly get out-of-hand. Before moving on from this though, note that there is a way to globally enable or disable the @IgnoreException behavior in the debugger.

This feature is enabled by default when the debugger starts; if that's all you need you can skip this section. To globally disable @IgnoreException handling, you can either just insert the following snippet where it executes once at the start of your program or, if desired, instrument your code to programatically enable and disable @IgnoreException handling according to runtime conditions as needed. A try-except block prevents the code from crashing when it's not being debugged or if the debugger isn't installed.

    # 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. Context-aware ignore
Moving on to the second option, I'll reset back to the original code, without the line annotations. This time, by changing the value of a secret debugger switch, the debugger will only stop on exceptions which are raised outside of the caller's immediate context. This is the skip_on_exceptions_thrown_in_same_context debugger flag, and it is not enabled by default, so if you want this behavior, you have to explicitly turn it on (as shown):

    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

Now the debugger only stops one time, versus stopping on three raised exceptions previously, in the first example. And I know what you're thinking, now it makes more sense to combine these two approaches, since there will typically be far fewer points in most code that will need annotating with @IgnoreException.

3. Combine both techniques
So here's the final version of the example which, even with both the RaisedExceptions and UncaughtExceptions options enabled, the VScode debugger runs all the way through without stopping:

    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...
Logo

开发云社区提供前沿行业资讯和优质的学习知识,同时提供优质稳定、价格优惠的云主机、数据库、网络、云储存等云服务产品

更多推荐