简体   繁体   English

在Python中分叉时,父进程和子进程之间的通信进程

[英]Communication between parent and child process when forking in Python

I was trying to have a Python program simultaneously run a processing loop, and a broadcasting service for the result, using a call to os.fork(), something like 我试图让一个Python程序同时运行一个处理循环,并使用os.fork()调用结果的广播服务,类似于

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

Here keep_updating_some_value_while_parent_is_running() , which is executed by the child, stores some value that it keeps updating as long as the parent is running. 这里由子keep_updating_some_value_while_parent_is_running()执行的keep_updating_some_value_while_parent_is_running()存储一些值,只要父keep_updating_some_value_while_parent_is_running()正在运行它就会保持更新。 It actually writes the value to disk so that the parent can easily access it. 它实际上将值写入磁盘,以便父级可以轻松访问它。 It detects the parent is running by checking that the web service that it runs is available. 它通过检查父运行的Web服务是否可用来检测父运行。

broadcast_value() runs a web service, when consulted it reads the most recent value from disk and serves it. broadcast_value()运行Web服务,在查阅时,它从磁盘读取最新值并提供服务。

This implementation works well, but it is unsatisfactory for several reasons: 这种实现很有效,但由于以下几个原因,它不能令人满意:

  1. The time.sleep(3) is necessary because the web service requires some startup time. time.sleep(3)是必要的,因为Web服务需要一些启动时间。 There is no guarantee at all that in 3 seconds the service will be up and running, while on the other hand it may be much earlier. 根本不能保证在3秒内服务将启动并运行,而另一方面它可能更早。

  2. Sharing data via disk is not always a good option or not even possible (so this solution doesn't generalize well). 通过磁盘共享数据并不总是一个好的选择,甚至不可能(因此这个解决方案不能很好地概括)。

  3. Detecting that the parent is running by checking that the web service is available is not very optimal, and moreover for different kinds of processes (that cannot be polled automatically so easily) this wouldn't work at all. 通过检查Web服务是否可用来检测父进程是不是最佳,而且对于不同类型的进程(不能自动轮询这么简单),这根本不起作用。 Moreover it can be that the web service is running fine, but there is a temporary availability issue. 此外,可能是Web服务运行正常,但存在临时可用性问题。

  4. The solution is OS dependent. 解决方案依赖于操作系统。

  5. When the child fails or exits for some reason, the parent will just keep running (this may be the desired behavior, but not always). 当孩子由于某种原因失败或退出时,父母将继续运行(这可能是期望的行为,但并非总是如此)。

What I would like would be some way for the child process to know when the parent is up and running, and when it is stopped, and for the parent to obtain the most recent value computed by the child on request, preferably in an OS independent way. 我希望通过某种方式让子进程知道父进程何时启动和运行,何时停止,以及父进程获取子请求时计算的最新值,最好是独立于操作系统方式。 Solutions involving non-standard libraries also are welcome. 涉及非标准库的解决方案也是受欢迎的。

I'd recommend using multiprocessing rather than os.fork() , as it handles a lot of details for you. 我建议使用multiprocessing而不是os.fork() ,因为它会为你处理很多细节。 In particular it provides the Manager class, which provides a nice way to share data between processes. 特别是它提供了Manager类,它提供了一种在进程之间共享数据的好方法。 You'd start one Process to handle getting the data, and another for doing the web serving, and pass them both a shared data dictionary provided by the Manager . 您将启动一个Process来处理获取数据,另一个用于执行Web服务,并将它们传递给Manager提供的共享数据字典。 The main process is then just responsible for setting all that up (and waiting for the processes to finish - otherwise the Manager breaks). 然后主要过程负责设置所有这些(并等待过程完成 - 否则Manager中断)。

Here's what this might look like: 这可能是这样的:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM