Last active
July 29, 2023 22:12
-
-
Save ruedesign/5218221 to your computer and use it in GitHub Desktop.
Python thread sample with handling Ctrl-C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
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()```
It does not work when there are many threads at the same time
Thanks 👍
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
Thanks for sharing your code. I've had trouble stopping threads using Ctrl-C and clearing up processes. This code works perfect for me.