2

I would like to handle one specific exception in my script in a single place without resorting to a try/exception everytime*. I was hoping that the code below would do this:

import sys

def handle(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, ValueError):
        print("ValueError handled here and the script continues")
        return
    # follow default behaviour for the exception
    sys.__excepthook__(exc_type, exc_value, exc_traceback)

sys.excepthook = handle

print("hello")
raise ValueError("wazaa")
print("world")
a = 1/0

The idea was that ValueError would be handled "manually" and the script would continue running (return to the script). For any other error (ZeroDivisionError in the case above), the normal traceback and script crash would ensue.

What happens is

$ python scratch_13.py
hello
ValueError handled here and the script continues

Process finished with exit code 1

The documentation mentions that (emphasis mine)

When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object. In an interactive session this happens just before control is returned to the prompt; in a Python program this happens just before the program exits.

which would mean that when I am in handler() it is already too late as the script has decided to die anyway and my only possibility is to influence how the traceback will look like.

Is there a way to ignore a specific exception globally in a script ?


* this is for a debugging context where the exception would normally be raised and crash the script (in production) but in some specific cases (a dev platform for instance), this specific exception needs to just be discarded. Otherwise I would have put a try/exception clause everywhere where the issue could arise.

WoJ
  • 27,165
  • 48
  • 180
  • 345
  • Look at [this](https://books.google.com.mx/books?id=GIibCgAAQBAJ&pg=PA34&lpg=PA34&dq=issubclass(exc_type,+ValueError)&source=bl&ots=dkL-A6Ofb6&sig=4U2vDlzUAHpXWh_M5Fc24htzkko&hl=es-419&sa=X&ved=0ahUKEwiNyNfz__faAhXJ61MKHbFeBVYQ6AEIKDAA#v=onepage&q=issubclass(exc_type%2C%20ValueError)&f=false) might help. – lalengua May 09 '18 at 06:30
  • @Mulliganaceous: I do not understand: which `except`? You mean in the code? If so this is exactly what I want to avoid doing (adding a `try` clause everywhere) – WoJ May 09 '18 at 06:43
  • @lalengua: this si interesting - but also means I have to wrap the whole script in a context manager. This is an idea, though. – WoJ May 09 '18 at 06:45
  • When you catch an exception, execution continues from the point where the exception was *caught*; you can't go back to the point where it was *raised*, which would mean having a global "handler" for an exception type wouldn't be particularly useful. – chepner Jul 26 '18 at 18:56
  • Possible duplicate of [How to continue a frame execution from last attempted instruction after handling an exception?](https://stackoverflow.com/questions/34425356/how-to-continue-a-frame-execution-from-last-attempted-instruction-after-handling) – ivan_pozdeev Jul 26 '18 at 18:59

1 Answers1

0

One way to do it is to use contextlib.suppress and have a global tuple of suppressed Exceptions:

 suppressed = (ValueError,)

And then anywhere where the error might occure you just wrap it in with suppress(*suppressed):

print("hello")
with suppress(*suppressed): # gets ignored
    raise ValueError("wazaa")
print("world")
a = 1/0 # raise ZeroDivisionError

And then in production you just change suppressed to ():

suppressed = ()
print("hello")
with suppress(*suppressed):
    raise ValueError("wazaa") # raises the error
print("world")
a = 1/0 # doesn't get executed

I think this is the best you can do. You can't ignore the exception completly globally, but you can make it so you only have to change on place.

MegaIng
  • 7,361
  • 1
  • 22
  • 35
  • Thanks but this is not too different from a `try` clause where the `except` would catch the specific exception and `pass`. My aim was not to modify the script code and just handle the exception in one place, outside of the normal flow of the script. – WoJ May 09 '18 at 06:39
  • Well, no - yours is better than having the try clause everywhere because, as you mention, you can modify the behavior globally. It still requires wrapping every call individually. – WoJ May 09 '18 at 06:48
  • @WoJ Yes, but you can't do any better without tweaking the python interpreter. – MegaIng May 09 '18 at 06:51