How do I capture SIGINT in Python?
Register your handler with signal.signal
like this:
#!/usr/bin/env python
import signal
import sys
def signal_handler(sig, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
signal.pause()
Code adapted from here.
More documentation on signal
can be found here.
python: catch SIGINT in process reading data from a socket
Looks like your internal loop is blocking progBreak
check, this code is working for me:
import signal
progBreak = False
def newBreakHandler(signum, frame):
global progBreak
progBreak = True
def runMain():
global progBreak
signal.signal(signal.SIGINT, newBreakHandler)
while not progBreak:
while not progBreak and client.poll():
command = client.recv_bytes()
print "Exiting..."
runMain()
Catch SIGINT and call a method in an object
I'm not sure why you added the part
When I try to add another argument to sigint_handler, I get an error.
to your Question, but i'll first cover that:
use a wrapper
or partial
(which is a wrapper-factory) like so:
>>> def my_wrapped_sigint_handler(my_argument):
... def signal_handler(signum, frame): # the actual sigint handler
... print(my_argument) # or do something useful
... return signal_handler
...
>>> signal.signal(signal.SIGINT, my_wrapped_sigint_handler('FOO'))
or using partial:
>>> from functools import partial
>>> def sigint_handler(signum, frame, my_argument):
... print(my_argument) # or do something useful
...
>>> signal.signal(signal.SIGINT, partial(sigint_handler, my_argument="foobar"))
to adress your original question using the technique above:
>>> class MyObject:
... def terminate (self):
... do_something()
...
>>> def sigint_handler(signum, frame, obj):
... obj.terminate()
...
>>> signal.signal(signal.SIGINT, partial(sigint_handler, obj=MyObject()))
will call MyObject
's instance's .terminate()
on ^C
.
How do I capture SIGINT in Python on Windows?
After opening the bug upstream the root cause of the problem was found and a patch was written. This patch won't be going into the python 2.x series.
Catch Ctrl+C / SIGINT and exit multiprocesses gracefully in python
The previously accepted solution has race conditions and it does not work with map
and async
functions.
The correct way to handle Ctrl+C/SIGINT
with multiprocessing.Pool
is to:
- Make the process ignore
SIGINT
before a processPool
is created. This way created child processes inheritSIGINT
handler. - Restore the original
SIGINT
handler in the parent process after aPool
has been created. - Use
map_async
andapply_async
instead of blockingmap
andapply
. - Wait on the results with timeout because the default blocking waits to ignore all signals. This is Python bug https://bugs.python.org/issue8296.
Putting it together:
#!/bin/env python
from __future__ import print_function
import multiprocessing
import os
import signal
import time
def run_worker(delay):
print("In a worker process", os.getpid())
time.sleep(delay)
def main():
print("Initializng 2 workers")
original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
pool = multiprocessing.Pool(2)
signal.signal(signal.SIGINT, original_sigint_handler)
try:
print("Starting 2 jobs of 5 seconds each")
res = pool.map_async(run_worker, [5, 5])
print("Waiting for results")
res.get(60) # Without the timeout this blocking call ignores all signals.
except KeyboardInterrupt:
print("Caught KeyboardInterrupt, terminating workers")
pool.terminate()
else:
print("Normal termination")
pool.close()
pool.join()
if __name__ == "__main__":
main()
As @YakovShklarov noted, there is a window of time between ignoring the signal and unignoring it in the parent process, during which the signal can be lost. Using pthread_sigmask
instead to temporarily block the delivery of the signal in the parent process would prevent the signal from being lost, however, it is not available in Python-2.
Related Topics
How to Do Fuzzy Match Merge With Python Pandas
Threading Pool Similar to the Multiprocessing Pool
Can't Send Input to Running Program in Sublime Text
Identify Groups of Continuous Numbers in a List
Can't Pickle ≪Type 'Instancemethod'≫ When Using Multiprocessing Pool.Map()
Normal Arguments Vs. Keyword Arguments
What Is an Alternative to Execfile in Python 3
How to Read Specific Lines from a File (By Line Number)
Pretty-Print an Entire Pandas Series/Dataframe
Asynchronous Requests With Python Requests
Can a Variable Number of Arguments Be Passed to a Function
How to Fix "Runtimeerror: Package Fails to Pass a Sanity Check" For Numpy and Pandas
When Is "I += X" Different from "I = I + X" in Python
Setting the Correct Encoding When Piping Stdout in Python
How to Save and Load Cookies Using Python + Selenium Webdriver