Run atexit() when python process is killed

13,031

Solution 1

Try signal.signal. It allows to catch any system signal:

import signal

def handle_exit():
    print('\nAll files saved in ' + directory)
    generate_output()

atexit.register(handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)

Now you can kill {pid} and handle_exit will be executed.

Solution 2

To enable signals when debugging PyCharm on Windows:

  1. Within PyCharm hit Ctrl + Shift + A to bring up the "Find Actions..." menu
  2. Search for "Registry" and hit enter
  3. Find the key kill.windows.processes.softly and enable it (you can start typing "kill" and it will search for the key)
  4. Restart PyCharm
Share:
13,031

Related videos on Youtube

Chan Jing Hong
Author by

Chan Jing Hong

A curious person who tends to dig very deep into the subjects that interest me. Founder, Software Architect at Groftware

Updated on November 01, 2022

Comments

  • Chan Jing Hong
    Chan Jing Hong over 1 year

    I have a python process which runs in background, and I would like it to generate some output only when the script is terminated.

    def handle_exit():
        print('\nAll files saved in ' + directory)
        generate_output()
    
    atexit.register(handle_exit)
    

    Calling raising a KeyboardInterupt exception and sys.exit() calls handle_exit() properly, but if I were to do kill {PID} from the terminal it terminates the script without calling handle_exit().

    Is there a way to terminate the process that is running in the background, and still have it run handle_exit() before terminating?

    • Alexander Ejbekov
      Alexander Ejbekov over 7 years
      Not possible with atexit alone. As the documentation states The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called. here
  • fish2000
    fish2000 over 4 years
    N.B., your handler function signatures should afford two positional arguments – a signal number and a stack frame, e.g. handle_exit(signum, frame) or handle_exit(*args) – as that’s how those functions invoked via signal.signal(…) will be called. If your functions take explicit arguments, you can set up values for atexit.register(…) to pass on its own invocation, e.g. atexit.register(handle_exit, None, None) or similar.
  • IlyaP
    IlyaP over 3 years
    Doesn't work on Windows when closing via Task Manager or via Stop button in PyCharm