首页 > 解决方案 > 使用其关闭方法停止子进程中的服务器

问题描述

我正在ServerWindows 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.

标签: pythonservermultiprocessingshutdown

解决方案


我终于自己想出了一个解决方案:

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.Poolconcurrent.futures.ProcessPoolExecutor),这可能是个问题。在这种情况下,应该在方法中multiprocessing.Event()替换为。multiprocessing.Manager().Event()__init__


推荐阅读