当使用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脚本退出。错误的是,每次我将新项目放入队列时,我都会创建更多的工作线程(我会为每个要运行的外部程序批量执行此操作)。所以当我进入第四个外部应用程序时,我有四个线程同时运行,即使我只认为我有一个。
答案 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()
请注意,这个也隐藏了窗口。