如何在Python多处理中优雅地关闭管道连接并中断子进程循环

slwdgvem  于 2022-12-10  发布在  Python
关注(0)|答案(1)|浏览(187)

我有一个体系结构,其中主进程可以产生子进程。
主进程通过管道向子进程发送计算请求。
下面是我当前的子进程代码:

while True:
            try:
                # not sufficient because conn.recv() is blocking
                if self.close_event.is_set():
                    break
                fun, args = self.conn.recv()
                # some heavy computation
                res = getattr(ds, fun)(*args)
                self.conn.send(res)
            except EOFError as err:
                # should be raised by conn.recv() if connection is closed
                # but it never happens
                break

以及它在主进程中的初始化方式:

def init_worker(self):
            close_event = DefaultCtxEvent()
            conn_parent, conn_child = Pipe()
            process = WorkerProcess(
                i, self.nb_workers, conn_child, close_event, arguments=self.arguments)
            process.daemon = True
            process.start()
            # close the side we don't use
            conn_child.close()
            # Remember the side we need
            self.conn = conn_parent

我有一个干净的方法,应该关闭所有的子进程,就像这样从主进程

def clean(self):
    self.conn.close()
    # waiting for the loop to break for a clean exit
    self.child_process.join()

然而,对conn.recv()的调用会阻塞,并且不会像我所期望的那样抛出错误。我可能在某种程度上混淆了“conn_parent”和“conn_children”的行为?
如何正确关闭儿童连接?
编辑:一个可能的解决方案是显式发送一条消息,内容类似于“_break”。循环通过conn.recv()接收消息并中断。这是一个“正常”模式吗?作为奖励,有没有办法在不终止进程的情况下杀死一个可能长时间运行的方法?

8i9zcol2

8i9zcol21#

显然有一个problem with linux Pipes,因为子节点派生了父节点的连接,它仍然是打开的,需要在子节点端显式关闭。
这只是一个如何实现虚拟示例。
第一个
这在Windows上是不需要的,或者当Linux使用“spawn”来创建worker时,因为子节点不会派生父节点连接,但是此代码将在具有任何worker创建策略的任何系统上工作。

相关问题