Skip to content

Instantly share code, notes, and snippets.

@ruedesign
Last active July 29, 2023 22:12
Show Gist options
  • Save ruedesign/5218221 to your computer and use it in GitHub Desktop.
Save ruedesign/5218221 to your computer and use it in GitHub Desktop.
Python thread sample with handling Ctrl-C
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, time, threading, abc
from optparse import OptionParser
def parse_options():
parser = OptionParser()
parser.add_option("-t", action="store", type="int", dest="threadNum", default=1,
help="thread count [1]")
(options, args) = parser.parse_args()
return options
class thread_sample(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
self.kill_received = False
def run(self):
while not self.kill_received:
# your code
print self.name, "is active"
time.sleep(1)
def has_live_threads(threads):
return True in [t.isAlive() for t in threads]
def main():
options = parse_options()
threads = []
for i in range(options.threadNum):
thread = thread_sample("thread#" + str(i))
thread.start()
threads.append(thread)
while has_live_threads(threads):
try:
# synchronization timeout of threads kill
[t.join(1) for t in threads
if t is not None and t.isAlive()]
except KeyboardInterrupt:
# Ctrl-C handling and send kill to threads
print "Sending kill to threads..."
for t in threads:
t.kill_received = True
print "Exited"
if __name__ == '__main__':
main()
@jaekookang
Copy link

Thanks for sharing your code. I've had trouble stopping threads using Ctrl-C and clearing up processes. This code works perfect for me.

@janlzlabs
Copy link

janlzlabs commented Jan 16, 2019

Here is another example of a simple HTTP server that shows how to handle signal SIGINT and SIGTERM. The server shuts down orderly when the main thread receives a signal, which causes an exception to be raised. The except clause calls cancel() that calls shutdown() and server_close().

import SocketServer as socketserver
import os
import threading, signal, time

class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    path_to_image = 'plot.png'
    img = open(path_to_image, 'rb')
    statinfo = os.stat(path_to_image)
    img_size = statinfo.st_size
    print(img_size)

def do_HEAD(self):
    self.send_response(200)
    self.send_header("Content-type", "image/png")
    self.send_header("Content-length", img_size)
    self.end_headers()

def do_GET(self):
    self.send_response(200)
    self.send_header("Content-type", "image/png")
    self.send_header("Content-length", img_size)
    self.end_headers() 
    f = open(path_to_image, 'rb')
    self.wfile.write(f.read())
    f.close() 
     

class MyServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    def __init__(self, server_adress, RequestHandlerClass):
        self.allow_reuse_address = True
        socketserver.TCPServer.__init__(self, server_adress, RequestHandlerClass, False)


class WorkerThread(threading.Thread):
    def __init__(self, target, sh, cl):
        threading.Thread.__init__(self)
        self.handler = target
        self.shut = sh
        self.close = cl

    def run(self):
        print 'Running thread', threading.currentThread().getName()
        self.handler()

    def cancel(self):
        print 'Cancel called'
        self.shut()
        self.close()
        

class ServerExit(Exception):
    pass


def service_shutdown(signum, frame):
    print('Caught signal %d' % signum)
    raise ServerExit


if __name__ == "__main__":
    signal.signal(signal.SIGTERM, service_shutdown)
    signal.signal(signal.SIGINT, service_shutdown)

    server = MyServer(("localhost", 7777), MyHandler)
    server.server_bind()
    server.server_activate()
    server_thread = WorkerThread(server.serve_forever, server.shutdown, server.server_close)
    try:
        server_thread.start()
        while True:
            time.sleep(1.0)
    except ServerExit:
        print('Caught exception ')
        server_thread.cancel()```

@joba14
Copy link

joba14 commented Jul 27, 2021

It does not work when there are many threads at the same time

@tobiasb
Copy link

tobiasb commented Nov 4, 2021

Thanks 👍

@joaoceron
Copy link

for python 3:
s/isAlive()/is_alive()/g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment