使用其关闭方法在子进程中停止服务器
Stopping a server in a subprocess with its shutdown method
我正在 Windows 10 上的 CPython 3.7 中实现一个 Server
class,其中一个 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()
调用不会影响运行ning子进程中的服务器实例。
我知道我可以用 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
接口(单处理 v. 多处理)并且我不希望客户处理 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()
它适用于任何一种情况:单处理(多线程)和多处理。
Remark. — 在 __init__
方法中使用 multiprocessing.Event()
时,Server
实例不再可选。如果想在进程池中调用 Server
实例(使用 multiprocessing.pool.Pool
或 concurrent.futures.ProcessPoolExecutor
),这可能是个问题。在这种情况下,应该在 __init__
方法中将 multiprocessing.Event()
替换为 multiprocessing.Manager().Event()
。
我正在 Windows 10 上的 CPython 3.7 中实现一个 Server
class,其中一个 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()
调用不会影响运行ning子进程中的服务器实例。
我知道我可以用 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
接口(单处理 v. 多处理)并且我不希望客户处理 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()
它适用于任何一种情况:单处理(多线程)和多处理。
Remark. — 在 __init__
方法中使用 multiprocessing.Event()
时,Server
实例不再可选。如果想在进程池中调用 Server
实例(使用 multiprocessing.pool.Pool
或 concurrent.futures.ProcessPoolExecutor
),这可能是个问题。在这种情况下,应该在 __init__
方法中将 multiprocessing.Event()
替换为 multiprocessing.Manager().Event()
。