在主进程中从stdin执行阻塞读取时,Python子进程阻塞

时间:2014-09-05 08:15:10

标签: python windows python-2.7 multiprocessing

我有一个Python多处理应用程序,它使用多处理API启动“worker”。主进程本身是由一个不是用Python编写的服务进程启动的。工作人员可以使用subprocess.Popen启动其他非Python子流程。

为清楚起见,这是整个流程层次结构:

  • service.exe:服务进程(原生EXE)
    • python.exe:Python主进程(程序如下)
      • python.exe:Python子进程(由Process启动的任务功能)
        • subprocess.exe:Native子进程(请参阅下面的说明)

当服务进程停止时,它必须告诉Python进程退出。我正在使用标准输入。优点是,如果服务进程崩溃或被杀死,那么Python进程的标准输入将被关闭,因此它将退出,并且不会有孤立进程。

import multiprocessing
import time
import sys


def task():
    print("Task started...")
    # TODO: Start a native process here using Subprocess.popen
    time.sleep(3)
    print("Task ended")

if __name__ == '__main__':
    process = multiprocessing.Process(target=task)
    process.start()

    # time.sleep(3)  # "workaround"
    sys.stdin.read()

    print("Terminating process...")
    process.terminate()

然而,似乎当我添加sys.stdin.read()时,Python子进程启动,但它没有做任何事情。它似乎挂了。

一个(坏)解决方法是在读取标准输入之前添加time.sleep(3)。然后上面的程序工作。但是,似乎Python子进程启动的子进程仍然可以阻塞,只有在主进程中执行阻塞读取时它们才会阻塞。

所有系统上都不会出现此问题。它是在一台Windows 8机器上观察到的,它从未发生在另一台Windows机器上。我使用的是Python 2.7.2。

我的问题是:主进程中的阻塞读取如何影响子进程?子流程不应该独立于主流程中的任何操作而启动和运行吗? (我只想了解这个问题。如果你找到一个更好的解决方案来阻止Python进程从服务进程,我会很感激,但这是奇怪的阻塞行为让我做恶梦)

1 个答案:

答案 0 :(得分:0)

您的子流程不会挂起。当我使用多处理库时,我最喜欢的调试技术之一是使子进程删除文本文件而不是打印到stdout,这样你就可以避免管道的所有复杂问题,比如你是否想知道子进程继承了相同的stdin / stdout,完整管道等。如果我们将您的任务修改为以下内容:

def task():
    with open('taskfile.txt', 'w') as fo:
        fo.write("Task started...")
        # TODO: Start a native process here using Subprocess.popen
        time.sleep(3)
        fo.write("Task ended")

它生成文本文件' taskfile.txt'其中包含以下内容:

  

任务已开始......任务已结束

因此,您的任务正在运行并且退出就好了。 Main只是等待stdin的输入。我怀疑你没有看到"任务开始......"请注意,因为使用multiprocessing.Process()启动的进程有自己的stdin和stdout管道,它们不能与主要管道连接到同一个控制台。

相关问题