从定时器线程终止进程
我先从代码开始说起。
from multiprocessing import Process, Event, Queue
from threading import Timer
from Queue import Empty
class MyServer(Process):
def __init__(self, port, queue):
Process.__init__(self)
self.port = port
self.queue = queue
self.sd = None
def run(self):
try:
self.start_serving()
except KeyboardInterrupt:
print("Shutting down..")
finally:
if self.sd is not None:
self.sd.close()
def start_serving(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sd = s
try:
s.bind(('', self.port))
s.listen(1)
while True:
conn, addr = s.accept()
while True:
# I dont want to bore you with excess code
# just recv data from clients
try:
msg = self.queue.get_nowait()
# here i start Timer with delay from message (I'll describe Message class below)
Timer(msg.delay, self.response_handler, args=(conn, msg)).start()
except Empty:
pass
conn.close()
finally:
s.close()
def response_handler(self, sd, msg):
# doesn't matter
# and now I want to terminate the MyServer instance
if msg.terminate:
# the problem is here. Lets call it 'problem line'
sys.exit()
msg
是 Message
类的一个实例,具体内容是:
class Message(object):
def __init__(self, port, delay, values, terminate=False):
self.port = port
self.delay = delay
self.values = values
self.terminate = terminate
我的逻辑是通过 TCP 连接从客户端获取数据,然后检查消息队列。消息是用来控制服务器的东西。有时候我会收到像“等待 3 秒然后终止服务器”这样的消息。
到目前为止,我做了以下几件事:
- 在
problem line
调用self.terminate()
。结果我得到了AttributeError: 'NoneType' object has no attribute 'terminate'
的错误。 - 在
problem line
抛出一个异常。我以为这个异常会在run()
函数中被捕获,但我错了。 - 调用
sys.exit()
。这也没有效果。
也许我的问题可以更简单一些。如何在 Python 中从线程中终止进程?
1 个回答
2
为什么不使用 multiprocessing.Event
呢(你已经导入了它)?如果收到终止消息,就可以优雅地退出进程。
要做到这一点,可以在 __init__
方法中添加以下内容:
self.exit = Event()
然后修改这两个 while
循环:
while True:
conn, addr = s.accept()
while True:
#...
改成:
while not self.exit.is_set():
conn, addr = s.accept()
while not self.exit.is_set()
#...
接着在你的响应处理器中:
if msg.terminate:
self.exit.set()
这样可以让代码自然地退出循环,确保调用 conn.close()
。