python - 使用其关闭方法停止子进程中的服务器
问题描述
我正在Server
Windows 10 上的 CPython 3.7 中实现一个类,该类具有一个Server.serve
永久启动服务的Server.shutdown
方法和一个停止服务的方法。我需要在子进程中运行多个服务器实例。
在子线程中运行服务器实例会按预期停止实例:
import threading
import time
class Server:
def __init__(self):
self.shutdown_request = False
def serve(self):
print("serving")
while not self.shutdown_request:
print("hello")
time.sleep(1)
print("done")
def shutdown(self):
print("stopping")
self.shutdown_request = True
if __name__ == "__main__":
server = Server()
threading.Thread(target=server.serve).start()
time.sleep(5)
server.shutdown()
但是,在子进程中运行服务器实例不会意外停止实例:
import multiprocessing
import time
class Server:
def __init__(self):
self.shutdown_request = False
def serve(self):
print("serving")
while not self.shutdown_request:
print("hello")
time.sleep(1)
print("done")
def shutdown(self):
print("stopping")
self.shutdown_request = True
if __name__ == "__main__":
server = Server()
multiprocessing.Process(target=server.serve).start()
time.sleep(5)
server.shutdown()
我怀疑在多处理情况下,self.shutdown_request
父进程和子进程之间不共享属性,因此server.shutdown()
调用不会影响子进程中正在运行的服务器实例。
我知道我可以解决这个问题multiprocessing.Event
:
import multiprocessing
import time
class Server:
def __init__(self, shutdown_event):
self.shutdown_event = shutdown_event
def serve(self):
print("serving")
while not self.shutdown_event.is_set():
print("hello")
time.sleep(1)
print("done")
if __name__ == "__main__":
shutdown_event = multiprocessing.Event()
server = Server(shutdown_event)
multiprocessing.Process(target=server.serve).start()
time.sleep(5)
shutdown_event.set()
但我想保留该Server.shutdown
方法,而不是Server
根据其用法(单处理与多处理)更改接口,并且我不希望客户处理multiprocessing.Event
.
解决方案
我终于自己想出了一个解决方案:
import multiprocessing
import time
class Server:
def __init__(self):
self.shutdown_event = multiprocessing.Event()
def serve(self):
print("serving")
while not self.shutdown_event.is_set():
print("hello")
time.sleep(1)
print("done")
def shutdown(self):
print("stopping")
self.shutdown_event.set()
if __name__ == "__main__":
server = Server()
multiprocessing.Process(target=server.serve).start()
time.sleep(5)
server.shutdown()
它适用于任何一种情况:单处理(多线程)和多处理。
评论。— 使用multiprocessing.Event()
in__init__
方法,Server
实例不再是可挑选的。如果想要调用Server
进程池中的实例(使用multiprocessing.pool.Pool
或concurrent.futures.ProcessPoolExecutor
),这可能是个问题。在这种情况下,应该在方法中multiprocessing.Event()
替换为。multiprocessing.Manager().Event()
__init__