5

I need to implement an atexit Python function that would get the last error object and check for it's type. If the type of python error corresponds to PHP's E_ERROR I should save the error's output to a file.

The PHP code I'm porting looks like so:

register_shutdown_function( "fatal_handler" );
function fatal_handler() {
  $error = error_get_last();
    if ($error != null && $error['type'] === E_ERROR)
        echo  "recordFatalError: {$error['message']}\n";
}

My code snap are as follows:

def fatal_handler():
   # How to get last error object?

atexit.register(fatal_handler)

I would be glad if somebody explained me how can I get the necessary functionality with python.

Christophe
  • 68,716
  • 7
  • 72
  • 138
ddnomad
  • 373
  • 3
  • 15

2 Answers2

3

I would use sys.last_value for this:

import atexit
import sys

def fatal_handler():
    try:
        e = sys.last_value
    except AttributeError: # no exception prior to execution of fatal_handler
        return

atexit.register(fatal_handler)

You may choose to use getattr(sys, 'last_value', None) in place of the EAFP approach above. It returns None if sys.last_value isn't available.

Alternatively, if there's just one function you want to run only when the interpreter shutdown is caused by an exception, you could use sys.excepthook:

import sys

def fatal_handler(type, value, traceback):
   e = value

sys.excepthook = fatal_handler
Community
  • 1
  • 1
vaultah
  • 44,105
  • 12
  • 114
  • 143
  • The problem with this approach is that `sys.last_value` can be referenced only if error has happened while it's not always true with `atexit` function. Also I need also a type of the exception not only the value (`sys.last_type`). – ddnomad Jul 31 '16 at 14:31
  • @ddnomad it's trivial to find the type of any object e.g. using `type`. There's also `sys.last_type` available. – vaultah Jul 31 '16 at 14:35
  • yet I'm interested in other possible ways of avoiding `try/except` blocks to check for these values to be present. – ddnomad Jul 31 '16 at 14:37
  • @ddnomad [What is the EAFP principle in Python?](http://stackoverflow.com/q/11360858/2301450) – vaultah Jul 31 '16 at 14:39
1

When an exception is raised and uncaught, the interpreter calls sys.excepthook with info about the exception. The default function prints out a given traceback and exception to sys.stderr. You can replace this function with a function which save this data. Later you can use this data in your atexit handler:

import atexit
import sys

class LastException:
    value     = None
    type      = None
    trackback = None

    @staticmethod
    def excepthook(type,value,trackback):
        LastException.type      = type
        LastException.value     = value
        LastException.trackback = trackback

    @staticmethod
    def register():
        sys.excepthook = LastException.excepthook

def fatal_handler():
   print('{0} {1}'.format( LastException.type, LastException.value))

LastException.register()
atexit.register(fatal_handler)

raise BaseException("I am an error") 
# should print: <class 'BaseException'> I am an error
napuzba
  • 6,033
  • 3
  • 21
  • 32