subprocess.wait()没有等待Popen进程完成(使用线程时)?

时间:2011-06-14 09:07:03

标签: python multithreading subprocess popen

当使用subprocess.Popen()从我的python脚本中使用线程生成同一应用程序的多个实例以使它们同时运行时,我遇到了一些问题。在每个线程中,我使用popen()调用运行应用程序,然后通过调用wait()等待它完成。问题似乎是wait() - 调用实际上并不等待该过程完成。我只使用一个线程进行实验,并在进程启动时以及完成时打印出文本消息。所以线程函数看起来像这样:

def worker():
    while True:
        job = q.get() # q is a global Queue of jobs
        print('Starting process %d' % job['id'])
        proc = subprocess.Popen(job['cmd'], shell=True)
        proc.wait()
        print('Finished process %d' % job['id'])
        job.task_done()

但即使我只使用一个线程,它也会在出现任何“完成进程...”消息之前打印出几个“正在启动进程...”消息。有wait()实际上没有等待的情况吗?我有几个不同的外部应用程序(C ++控制台应用程序),它们将同时运行多个实例,对于其中一些我的代码可以工作,但对于其他实例,它不会。外部应用程序是否存在某些问题会以某种方式影响对wait()的调用? 创建线程的代码如下所示:

for i in range(1):
    t = Thread(target=worker)
    t.daemon = True
    t.start()
q.join() # Wait for the queue to empty

更新1 : 我还应该补充一点,对于某些外部应用程序,我有时会得到-1073471801的返回码(proc.returncode)。例如,其中一个外部应用程序会在前两次调用返回代码Popen,而不是最后两次(当我有四个作业时)。

更新2 : 为了清理,现在我在队列中有四个作业,这是四个不同的测试用例。当我运行我的代码时,对于其中一个外部应用程序,前两个Popen - 调用生成返回代码-1073471801。但是,如果我打印Popen调用的确切命令,并在命令窗口中运行它,它会毫无问题地执行。

解决! 我设法解决了我遇到的问题。我认为问题在于我缺乏线程编程的经验。我错过了这样一个事实:当我创建了我的第一个工作线程时,他们会一直活着直到python脚本退出。错误的是,每次我将新项目放入队列时,我都会创建更多的工作线程(我会为每个要运行的外部程序批量执行此操作)。所以当我进入第四个外部应用程序时,我有四个线程同时运行,即使我只认为我有一个。

4 个答案:

答案 0 :(得分:13)

您也可以使用check_call()代替Popen。 check_call()等待命令完成,即使shell=True然后返回作业的退出代码。

答案 1 :(得分:9)

遗憾的是,在使用shell=True运行子流程时,wait()只会等待sh子流程完成,而不会等待命令cmd

我会建议是否可以不使用shell=True,如果不可能,您可以创建一个类似于此answer的流程组,并使用os.waitpid等待流程不只是shell过程。

希望这有用:)

答案 2 :(得分:0)

确保您正在呼叫的所有应用程序在完成后都具有有效的系统返回码

答案 3 :(得分:0)

我也有问题,但受到了你的启发。

我看起来像这样,并且工作得很漂亮:

    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
    proc = subprocess.Popen(command, startupinfo=startupinfo)
    proc.communicate()
    proc.wait()

请注意,这个也隐藏了窗口。