patternpythonMinor
Handling signals in Python inside a function
Viewed 0 times
handlingfunctionsignalspythoninside
Problem
I have code that needs to exit gracefully. To simplify things, I am presenting an example based on the answer given here.
Since I need to handle a few signals, I thought of putting this logic in a function:
Thus, the main block of the python code should be:
This will fail however, since the
Therefore, my solution was to create
```
import signal
import time
import sys
original_sigint = None
def run_program():
while True:
time.sleep(1)
print("a")
def exit_gracefully(signum, frame):
# restore the original signal handler as otherwise evil things will happen
# in raw_input when CTRL+C is pressed, and our signal handler is not re-entrant
global original_sigint
signal.signal(signal.SIGINT, original_sigint)
try:
if raw_input("\nReally quit? (y/n)> ").lower().startswith('y'):
sys.exit(1)
except KeyboardInterrupt:
print("Ok ok, quitting")
sys.exit(1)
# restore the exit gracefully handler here
signal.signal(signal.SIGINT, exit_gracefully)
def set_signals():
global original_sigint
original_sigint = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGTERM, exit_gracefully)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGALRM, exit_gracefully)
signal.signal(signal.SIGHUP, signal.SIG_IGN)
if __name__ == '__main__':
# store the original SIGINT hand
Since I need to handle a few signals, I thought of putting this logic in a function:
def set_signals():
original_sigint = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGTERM, exit_gracefully)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGALRM, exit_gracefully)
signal.signal(signal.SIGHUP, signal.SIG_IGN)Thus, the main block of the python code should be:
if __name__ == '__main__':
# store the original SIGINT handler
set_signals()
run_program()This will fail however, since the
exit_gracefully does not know the variable original_init. Therefore, my solution was to create
original_sigint as a global variable. ```
import signal
import time
import sys
original_sigint = None
def run_program():
while True:
time.sleep(1)
print("a")
def exit_gracefully(signum, frame):
# restore the original signal handler as otherwise evil things will happen
# in raw_input when CTRL+C is pressed, and our signal handler is not re-entrant
global original_sigint
signal.signal(signal.SIGINT, original_sigint)
try:
if raw_input("\nReally quit? (y/n)> ").lower().startswith('y'):
sys.exit(1)
except KeyboardInterrupt:
print("Ok ok, quitting")
sys.exit(1)
# restore the exit gracefully handler here
signal.signal(signal.SIGINT, exit_gracefully)
def set_signals():
global original_sigint
original_sigint = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGTERM, exit_gracefully)
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGALRM, exit_gracefully)
signal.signal(signal.SIGHUP, signal.SIG_IGN)
if __name__ == '__main__':
# store the original SIGINT hand
Solution
What about implementing your signal handling code inside a class? This could look something like the following:
You can then use this in your code as follows:
You'll find more examples of how to use the with-statement on the web.
class GracefulExit:
def __enter__(self):
# set up signals here
# store old signal handlers as instance variables
def __exit__(self, type, value, traceback):
# restore old signal handlersYou can then use this in your code as follows:
with GracefulExit():
# Signals will be caught inside this block.
# Signals will no more be caught here.You'll find more examples of how to use the with-statement on the web.
Code Snippets
class GracefulExit:
def __enter__(self):
# set up signals here
# store old signal handlers as instance variables
def __exit__(self, type, value, traceback):
# restore old signal handlerswith GracefulExit():
# Signals will be caught inside this block.
# Signals will no more be caught here.Context
StackExchange Code Review Q#54348, answer score: 8
Revisions (0)
No revisions yet.