Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Why does `sys.exit(msg)` called from a thread not print `msg` to stderr?

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

like image 444
Dr. Jan-Philip Gehrcke Avatar asked Jul 30 '09 20:07

Dr. Jan-Philip Gehrcke


1 Answers

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!).

like image 173
Alex Martelli Avatar answered Oct 15 '22 19:10

Alex Martelli