views:

442

answers:

2

Hello!

Today I ran against the fact, that sys.exit() called from a child-thread does not kill the main process. I did not know this before, and this is okay, but I needed long time to realize this. It would have saved much much time, if sys.exit(msg) would have printed msg to stderr. But it did not.

It turned out that it wasn't a real bug in my application; it called sys.exit(msg) with a meaningful error in a volitional way -- but I just could not see this.

In the docs for sys.exit() it is stated: "[...] any other object is printed to sys.stderr and results in an exit code of 1"

This is not true for a call from a child-thread, where sys.exit() obviously behaves as thread.exit(): "Raise the SystemExit exception. When not caught, this will cause the thread to exit silently"

I think when a programmer wants sys.exit(msg) to print an error message, then this should just be printed -- independent of the place from where it is called. Why not? I currently don't see any reason. At least there should be a hint in the docs for sys.exit() that the message is not printed from threads.

What do you think? Why are error messages concealed from threads? Does this make sense?

Best regards,

Jan-Philip Gehrcke

A: 

Not all threads in python are equal. Calling sys.exit from a thread, does not actually exit the system. Thus, calling sys.exit() from a child thread is nonsensical, so it makes sense that it does not behave the way you expect.

This page talks more about threading objects, and the differences between threads and the special "main" thread.

Christopher
+4  A: 

I agree that the Python docs are incorrect, or maybe more precisely incomplete, regarding sys.exit and SystemExit when called/raised by threads other than the main one; please open a doc issue on the Python online tracker so this can be addressed in a future iteration of the docs (probably a near-future one -- doc fixes are easier and smoother than code fixes;-).

The remedy is pretty easy, of course -- just wrap any function you're using as the target of a threading.Thread with a decorator that does a try/except SystemExit, e: around it, and performs the "write to stderr" extra functionality you require (or, maybe better, uses a logging.error call instead) before terminating. But, with the doc issue that you correctly point out, it's hard to think about doing that unless and until one has met with the problem and in fact has had to spend some time in debugging to pin it down, as you've had to do (on the collective behalf of the core python developers -- sorry!).

Alex Martelli
You gave me a good advice, again ;)Btw: It's so great that you share your knowledge here. I see that you currently spend much of your time to fill up this platform with pure expert Python stuff! This is what the community needs but that's not a matter of course. A very very big Thank You for this!Jan-Philip
Jan-Philip Gehrcke
@Jan-Philip, you're most welcome, and, thank YOU for the kudos, it's always great to hear I'm being of help!
Alex Martelli