3

In my real case a Segmentation fault arises in the finally clause which I can't do anything about because it stems from an external library used via ctypes. Actually, I don't care about this segfault because the script is done anyway.

However, the segfault in the finally eats all Exceptions occuring prior to it. Thus, debugging that first NameError from iDontExist becomes a pain in the ass. It doesn't occur anywhere. Currently there is no way of seeing any raised Exceptions from before the segfault.

def f1():
    try:
        while True:
            pass
    except KeyboardInterrupt:
        print iDontExist

if __name__=="__main__":
    try:
        f1()
    finally:
        raise Exception("segfault here")
        print "finally"

What do you think I could do about it? Fixing the external library is not an option.

mknaf
  • 862
  • 8
  • 14
  • 1
    A segfault isn't an `Exception`; it's a signal that causes the OS to kill your program, not something you can catch in an `except` block. If you just want to make sure anything buffered before the segfault is written, you could try `sys.stdout.flush(); sys.stderr.flush()` before the line that might segfault. If you want to catch and log the exception before the segfault, put an `except` block before the `finally` to log it. If you want something else… what do you want? – abarnert Feb 27 '13 at 00:47
  • If I put `sys.stdout.flush(); sys.stderr.flush()` before the `raise Exception("segfault here")` it still doesn't show the `NameError`. What I want: see any Exceptions being raised before anything that happens in the `finally` clause – mknaf Feb 27 '13 at 01:00
  • Well, yes, that's because the `NameError` hasn't been printed yet. It gets printed as part of the normal exit-interpreter-via-uncaught-exception. If you don't exit that way, you need to get it printed in some other way. (As in EOL's sample.) – abarnert Feb 27 '13 at 01:12
  • 1
    Instead of manually flushing stdout/stderr, try `python -u` for unbuffered binary stdout,stderr. Does that make a difference? – smci Aug 20 '14 at 18:02

1 Answers1

4

You can try to catch exceptions before your finally:

try:
    f1()
except NameError as error:  # Change as needed
    print "Error caught:", error  # Or simply "raise", in order to raise the error caught
finally:
    raise Exception("segfault here")
    print "finally"

That said, abamert is right: a segmentation fault is not an exception, so you might be looking for something else.

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
  • It would be better to show, e.g., `except Exception as e:` and then code that prints out something based on `e`, instead of just the comments. – abarnert Feb 27 '13 at 00:48
  • Meanwhile, I'm still not 100% clear on what the OP wants, but if he just wants to see something about the `NameError` before a segfault in the `finally` kills his interpreter, this is exactly the way to do it. – abarnert Feb 27 '13 at 00:49
  • @abamert: I put an explicit example. – Eric O. Lebigot Feb 27 '13 at 00:50
  • Yeah this is probably the best way to do it. It's still missing line numbers etc. Better than nothing, though. – mknaf Feb 27 '13 at 01:02
  • 1
    @user1085954: Instead of just printing `error`, you can print the whole traceback. See the [`traceback`](http://docs.python.org/2/library/traceback.html) module, the [`exc_info`](http://docs.python.org/2/library/sys.html#sys.exc_info) function, etc. for details. I think EOL was just giving you a sample of what you can do, not trying to write the whole thing for you. – abarnert Feb 27 '13 at 01:12
  • @user1085954: I added in the code, as a comment, that you can also do `raise` and recover the full, usual Python error output. – Eric O. Lebigot Feb 27 '13 at 09:15
  • @EOL: False. It doesn't raise the `NameError` with `raise`. This shows the full range of my original problem: every Exception prior to an Exception (or program crash) in the finally clause is being eaten. – mknaf Feb 27 '13 at 09:59
  • @user1085954: I am not sure I understand what you mean (because replacing `f1()` by `raise NameError("error")` does make `raise` re-raise the `NameError` exception). In any case, if you need to catch an exception in the `finally` clause, you need to use another `try… except` structure *there* (i.e. inside the `finally` clause). – Eric O. Lebigot Feb 27 '13 at 12:12