[Python] Info su cancellazione traceback

Marco Giusti marco.giusti a posteo.de
Sab 19 Nov 2022 10:47:42 CET


On 19.11.2022 08:45, Matteo Boscolo wrote:
> Buongiorno a tutti,
> 
> vorrei cancellare il traceback di python e mostrare solo il mio raise,
> questa cosa mi serve per evitare che lo stack dell'errore venga visto
> in console.
> 
> ho provato con questo decoratore
> 
> def avoid_traceback(message=''):
>     ''' call a function a number of times '''
>     def decorate(fn):
>         @wraps(fn)
>         def wrapper(*args, **kwargs):
>             try:
>                 result = fn(*args, **kwargs)
>             except Exception as ex:
>                 if message:
>                     raise Exception(message)
>                 raise Exception("Error on method %s" % fn.__name__)
>             return result
>         return wrapper
>     return decorate
> 
> 
> che funziona, ma il traceback resta attivo, nel senso che se metto
> 
> traceback.print_exc()
> 
> mi vedo tutto lo stack dell'errore:
> 
> Traceback (most recent call last):
>   File "/media/OneTDisk/workspace/test.py", line 133, in wrapper
>     result = fn(*args, **kwargs)
>   File "/media/OneTDisk/workspace/test.py", line 218, in rise
>     raise Exception("rise")
> Exception: rise
> 
> 
> potete provare con questo esempietto qua:
> 
> class A(object):
>     def __init__(self):
>         pass
> 
>     @avoid_traceback("errore generico")#
>     def rise1(self):
>         return self.rise()
> 
>     @avoid_traceback("errore generico")#
>     def rise(self):
>         raise Exception("rise")
> a=A()
> a.rise1()
> traceback.print_exc()
> 
> ho trovato in rete
> 
> https://www.programcreek.com/python/example/119512/traceback.clear_frames
> 
> ma sembra che non funzioni..
> 
> qualche idea ?


Ciao Matteo,

vorrei premettere che non trovo sia una buona idea nascondere
informazioni quando si ha a che fare con delle eccezioni, anzi, piu'
informazioni ci sono e meglio e'. Comunque, usa il costrutto

     raise exception from None

Quando lanci un'eccezione al momento in cui ne stai gia' gestendo
un'altra, le due eccezioni sono concatenate in due punti: __context__ e
__cause__. Il primo attributo e' settato automaticamente e per
sovrascriverlo hai bisogno di un ulteriore blocco try/except. Non farlo,
perche' per visualizzare il traceback e' usato __suppress_context__.

Se il valore e' False, allora viene visualizzato __cause__ o
__context__, se il valore e' True, allora la precedente eccezione non e'
visualizzata. Usando "raise ... from None: ottieni gia' quello
che desideri: __cause__ e' settato to None e __suppress_context__ e'
settato to True.

Ecco qualche esempio usando sempre questo codice e usando il decoratore
"avoid_traceback" solo sul metodo "rise1".

     a = A()
     try:
         a.rise1()
     except Exception as exc:
         print(f"exc.__cause__: {exc.__cause__}")
         print(f"exc.__suppress_context__: {exc.__suppress_context__}")
         print(f"exc.__context__: {exc.__context__}")
         raise
     traceback.print_exc()


Esempio 1, lasciando il decoratore invariato:

     $ python3 hide_traceback.py
     exc.__cause__: None
     exc.__suppress_context__: False
     exc.__context__: rise
     Traceback (most recent call last):
       File "/home/marco/hide_traceback.py", line 11, in wrapper
         result = fn(*args, **kwargs)
       File "/home/marco/hide_traceback.py", line 27, in rise1
         return self.rise()
       File "/home/marco/hide_traceback.py", line 30, in rise
         raise Exception("rise")
     Exception: rise

     During handling of the above exception, another exception occurred:

     Traceback (most recent call last):
       File "/home/marco/hide_traceback.py", line 35, in <module>
         a.rise1()
       File "/home/marco/hide_traceback.py", line 14, in wrapper
         raise Exception(message)
     Exception: errore generico

Esempio 2, usando raise ... from None

     $ python3 hide_traceback.py
     exc.__cause__: None
     exc.__suppress_context__: True
     exc.__context__: rise
     Traceback (most recent call last):
       File "/home/marco/hide_traceback.py", line 35, in <module>
         a.rise1()
       File "/home/marco/hide_traceback.py", line 14, in wrapper
         raise Exception(message) from None
     Exception: errore generico

Esempio 3, usando un ulteriore blocco try/catch


     ...
     try:
         try:
             result = fn(*args, **kwargs)
         except Exception as ex:
             if message:
                 raise Exception(message) from None
             raise Exception("Error on method %s" % fn.__name__) from 
None
     except Exception as exc:
         exc.__context__ = None
         raise exc

     $ python3 hide_traceback.py
     exc.__cause__: None
     exc.__suppress_context__: True
     exc.__context__: None
     Traceback (most recent call last):
       File "/home/marco/hide_traceback.py", line 39, in <module>
         a.rise1()
       File "/home/marco/hide_traceback.py", line 19, in wrapper
         raise exc
       File "/home/marco/hide_traceback.py", line 15, in wrapper
         raise Exception(message) from None
     Exception: errore generico



Maggiori informazioni sulla lista Python