我试图在Python中运行一堆守护进程线程,并处理按Ctrl + C或中断时要触发的信号。我第一次启动它只有一个线程在运行,第二次它只有2个线程,依此类推。它会继续生成线程,并且无法正确关闭它们。任何人都可以指出为什么worker.join在通话
中不起作用# -*- coding: utf-8 -*-
"""
An example url status checker that uses events to stop threads.
"""
import threading
import queue
import signal
import sys
import requests
import time
import redis
# Create redis client
redis_client = redis.Redis()
pubsub = redis_client.pubsub()
# Subscribe to values channel
pubsub.subscribe("values")
class StatusChecker(threading.Thread):
"""
The thread that will check HTTP statuses.
"""
#: An event that tells the thread to stop
stopper = None
def __init__(self, stopper):
super().__init__()
self.stopper = stopper
# Run the thread in daemon mode
self.daemon = True
def run(self):
while not self.stopper.is_set():
try:
# Infinitely listen to pubsub messages
for message in pubsub.listen():
# this will throw queue.Empty immediately if there's
# no tasks left
print(message, self.getName())
except Exception as e:
print(e)
class SignalHandler:
"""
The object that will handle signals and stop the worker threads.
"""
#: The stop event that's shared by this handler and threads.
stopper = None
#: The pool of worker threads
workers = None
def __init__(self, stopper, workers):
self.stopper = stopper
self.workers = workers
def __call__(self, signum, frame):
"""
This will be called by the python signal module
https://docs.python.org/3/library/signal.html#signal.signal
"""
self.stopper.set()
# Join the workers
for worker in self.workers:
worker.join()
sys.exit(0)
if __name__ == '__main__':
# all the variables we'll need
num_workers = 1
stopper = threading.Event()
# we need to keep track of the workers but not start them yet
workers = [StatusChecker(stopper) for i in range(num_workers)]
# create our signal handler and connect it
handler = SignalHandler(stopper, workers)
signal.signal(signal.SIGINT, handler)
# start the threads!
for i, worker in enumerate(workers):
print('Starting worker {}'.format(i))
worker.start()