【问题标题】:Communication between parent and child process when forking in Python在 Python 中分叉时父子进程之间的通信
【发布时间】:2018-07-18 05:56:23
【问题描述】:

我试图让一个 Python 程序同时运行一个处理循环,并为结果提供一个广播服务,使用对 os.fork() 的调用,类似于

pid = os.fork()
if pid == 0:
    time.sleep(3)
    keep_updating_some_value_while_parent_is_running()
else:
    broadcast_value()

这里的keep_updating_some_value_while_parent_is_running(),由子进程执行,存储一些值,只要父进程运行,它就会不断更新。它实际上将值写入磁盘,以便父级可以轻松访问它。它通过检查父节点运行的 Web 服务是否可用来检测父节点是否正在运行。

broadcast_value() 运行 Web 服务,当被咨询时,它会从磁盘读取最新值并提供服务。

这种实现效果很好,但由于以下几个原因并不令人满意:

  1. time.sleep(3) 是必需的,因为 Web 服务需要 一些启动时间。根本无法保证服务会在 3 秒内启动并运行,而另一方面可能会更早。

  2. 通过磁盘共享数据并不总是一个好的选择,甚至不可能(因此这个解决方案不能很好地推广)。

  3. 通过检查 Web 服务是否可用来检测父进程是否正在运行并不是非常理想的,而且对于不同类型的进程(不能如此容易地自动轮询),这根本不起作用。此外,可能是 Web 服务运行良好,但存在临时可用性问题。

  4. 解决方案取决于操作系统。

  5. 当孩子因某种原因失败或退出时,父母只会保持 运行(这可能是期望的行为,但并非总是如此)。

我希望通过某种方式让子进程知道父进程何时启动并运行,何时停止,并让父进程根据请求获取子进程计算的最新值,最好在一种独立于操作系统的方式。也欢迎涉及非标准库的解决方案。

【问题讨论】:

    标签: python fork ipc


    【解决方案1】:

    我建议使用multiprocessing 而不是os.fork(),因为它会为您处理很多细节。特别是它提供了Manager 类,它提供了一种在进程之间共享数据的好方法。您将启动一个Process 来处理获取数据,另一个用于进行网络服务,然后将Manager 提供的共享数据字典传递给它们。然后主进程只负责设置所有这些(并等待进程完成 - 否则 Manager 会中断)。

    这可能是这样的:

    import time
    from multiprocessing import Manager, Process
    
    def get_data():
        """ Does the actual work of getting the updating value. """
    
    def update_the_data(shared_dict):
        while not shared_dict.get('server_started'):
            time.sleep(.1)
        while True:
            shared_dict['data'] = get_data()
            shared_dict['data_timestamp'] = time.time()
            time.sleep(LOOP_DELAY)
    
    
    def serve_the_data(shared_dict):
        server = initialize_server() # whatever this looks like
        shared_dict['server_started'] = True
        while True:
            server.serve_with_timeout()
            if time.time() - shared_dict['data_timestamp'] > 30:
                # child hasn't updated data for 30 seconds; problem?
                handle_child_problem()
    
    
    if __name__ == '__main__':
        manager = Manager()
        shared_dict = manager.dict()
        processes = [Process(target=update_the_data, args=(shared_dict,)),
            Process(target=serve_the_data, args=(shared_dict,))]
        for process in processes:
            process.start()
        for process in processes:
            process.join()
    

    【讨论】:

    • 太好了,谢谢!这正是我想要的。
    • 不客气!如果它解决了您的问题,请记住接受答案,以便未来的搜索者更好地了解什么是有效的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 2017-12-19
    • 2010-09-18
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    相关资源
    最近更新 更多