Search code examples
pythonipythonpdbipdb

How to automatically switch to debug mode on a warning?


I want to debug a warning that occurs well into the code's execution.

A simple breakpoint won't do, because the line that results in the warning executes millions of times without warning before the first warning occurs.

Also, the line where this is happening is in library code (more precisely, in pandas/core/common.py), so my preference is not to modify the code at all.

I just want to stop the program's execution right when it emits the warning, and inspect the stack at this point, either with pdb or with ipdb.

Is there a way to configure either debugger to automatically enter single-step mode upon the issuing of a warning?


Solution

  • You can write a script dbg.py:

    import pdb, warnings, sys
    import __builtin__
    
    if __name__ == '__main__':
        args, n = [], len(sys.argv)
        if n < 2:
            sys.exit(1)
        elif n > 2:
            args.append(__builtin__.__dict__[sys.argv[2]])
            if n > 3:
                args.append(int(sys.argv[3]))
        warnings.simplefilter('error', *args)  # treat warnings as exceptions
        try:
            execfile(sys.argv[1])
        except:
            pdb.post_mortem(sys.exc_info()[-1])
    

    You can then use it to debug your script like that. Pass in your script name as the first argument if you want to run pdb on any warning:

    $ python dbg.py yourscript.py
    

    Pass in warning type as the second argument if you only want pdb to run when some particular type of warning is raised:

    $ python dbg.py yourscript.py DeprecationWarning
    

    Line number as the third argument:

    $ python dbg.py yourscript.py DeprecationWarning 342
    

    You can also rewrite the code using warnings.filterwarnings instead of warnings.simplefilter to make warnings filtering even more flexible.