Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raising errors without traceback

I would like to use raise without printing the traceback on the screen. I know how to do that using try ..catch but doesn't find a way with raise.

Here is an example:

def my_function(self):
    resp = self.resp
    if resp.status_code == 404:
        raise NoSuchElementError('GET'+self.url+'{}'.format(resp.status_code)) 
    elif resp.status_code == 500:
        raise ServerErrorError('GET'+self.url+'{}'.format(resp.status_code))

When executing this, if I have a 404, the traceback will print on the screen.

Traceback (most recent call last):
  File "test.py", line 32, in <module>
    print ins.my_function()
  File "api.py", line 820, in my_function
    raise NoSuchElementError('GET ' + self.url + ' {} '.format(resp.status_code)) 

This is an API wrapper and I don't want users to see the traceback but to see the API response codes and error messages instead.

Is there a way to do it ?

like image 400
4m1nh4j1 Avatar asked Dec 15 '22 04:12

4m1nh4j1


2 Answers

I ran into a similar problem where a parent class was using the exception value on raise to pass messages through but where I didn't want to dump the traceback. @lejlot gives a great solution using sys.excepthook but I needed to apply it with a more limited scope. Here's the modification:

import sys
from contextlib import contextmanager

@contextmanager
def except_handler(exc_handler):
    "Sets a custom exception handler for the scope of a 'with' block."
    sys.excepthook = exc_handler
    yield
    sys.excepthook = sys.__excepthook__

Then, to use it:

def my_exchandler(type, value, traceback):
    print(': '.join([str(type.__name__), str(value)]))

with except_handler(my_exchandler):
    raise Exception('Exceptional!')

# -> Exception: Exceptional!

That way, if an exception isn't raised in the block, default exception handling will resume for any subsequent exceptions:

with except_handler(my_exchandler):
    pass

raise Exception('Ordinary...')

# -> Traceback (most recent call last):
# ->   File "raise_and_suppress_traceback.py", line 22, in <module>
# ->     raise Exception('Ordinary...')
# -> Exception: Ordinary...
like image 194
Alec Avatar answered Jan 07 '23 17:01

Alec


The problem is not with raising anything, but with what python interpreter does, when your program terminates with an exception (and it simply prints the stack trace). What you should do if you want to avoid it, is to put try except block around everything that you want to "hide" the stack trace, like:

def main():
  try:
    actual_code()
  except Exception as e:
    print(e)

The other way around is to modify the exeption handler, sys.excepthook(type, value, traceback), to do your own logic, like

def my_exchandler(type, value, traceback):
  print(value)

import sys
sys.excepthook = my_exchandler

you can even condition of exception type and do the particular logic iff it is your type of exception, and otherwise - backoff to the original one.

like image 28
lejlot Avatar answered Jan 07 '23 16:01

lejlot