Search code examples
pythonpython-3.xexceptionsyskeyboardinterrupt

How to properly setup sys.excepthook


I have written the following code to understand the sys.excepthook on a multiprocess environment. I am using python 3. I have created 2 processes which would print and wait for getting ctrl+c.

from multiprocessing import Process
import multiprocessing
import sys
from time import sleep


class foo:
    def f(self, name):
        try:
            raise ValueError("test value error")
        except ValueError as e:
            print(e)
        print('hello', name)
        while True:
            pass


def myexcepthook(exctype, value, traceback):
    print("Value: {}".format(value))
    for p in multiprocessing.active_children():
        p.terminate()


def main(name):
    a = foo()
    a.f(name)

sys.excepthook = myexcepthook
if __name__ == '__main__':
    for i in range(2):
        p = Process(target=main, args=('bob', ))
        p.start()

I was expecting the following result when I press ctrl+C

python /home/test/test.py
test value error
hello bob
test value error
hello bob

Value: <KeyboardInterrupt>

But unfortunately, I got the following result.

/home/test/venvPython3/bin/python /home/test/test.py
test value error
hello bob
test value error
hello bob
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
Process Process-1:
  File "/usr/lib/python3.6/multiprocessing/popen_fork.py", line 28, in poll
    pid, sts = os.waitpid(self.pid, flag)
KeyboardInterrupt
Traceback (most recent call last):
  File "/usr/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python3.6/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "/home/test/test.py", line 26, in main
    a.f(name)
  File "/home/test/test.py", line 15, in f
    pass
KeyboardInterrupt
Process Process-2:
Traceback (most recent call last):
  File "/usr/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python3.6/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "/home/test/test.py", line 26, in main
    a.f(name)
  File "/home/test/test.py", line 15, in f
    pass
KeyboardInterrupt

Process finished with exit code 0

It will be a great help if somebody could point out what am I doing wrong. Also, please let me know how to get the expected output.


Solution

  • You almost did it. At first, use exctype to print:

    def myexcepthook(exctype, value, traceback):
        print("Value: {}".format(exctype))
        for p in multiprocessing.active_children():
            p.terminate()
    

    And join() created processes, to prevent premature exit

    if __name__ == '__main__':
        pr = []
        for i in range(2):
            p = Process(target=main, args=('bob', ))
            p.start()
            pr.append(p)
        for p in pr:
            p.join()