我有一个Python多处理应用程序,它使用多处理API启动“worker”。主进程本身是由一个不是用Python编写的服务进程启动的。工作人员可以使用subprocess.Popen
启动其他非Python子流程。
为清楚起见,这是整个流程层次结构:
当服务进程停止时,它必须告诉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进程从服务进程,我会很感激,但这是奇怪的阻塞行为让我做恶梦)
答案 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管道,它们不能与主要管道连接到同一个控制台。