python并行进程返回退出代码

时间:2017-03-01 00:16:53

标签: python subprocess

让我看看我是否能说清楚...我是一个完全的Python初学者,所以请耐心等待,这是我的第一个python程序(虽然我熟悉其他一些语言的基本脚本)。我一直在寻找几个小时,我确信答案很简单,但我还没有让它正常工作。

我正在编写一个应该启动多个命令行进程的代码,当每个进程完成时,我想要更新QTableWidget中的一个单元格。该表为每个要运行的进程都有一行,每行都有一个用于进程“状态”的单元格。

我可以运行这个没问题,如果我只是做一个for循环,使用subprocess.call()每行产生一个进程但是这太线性了,我想同时将它们全部关闭而不是挂起每个循环周期的程序。我一直在挖掘子流程文档,并且很难用它。我知道我需要使用subprocess.Popen(这将阻止我的程序在进程运行时挂起,因此我可以生成多个实例)。我遇到麻烦的地方是退出退出代码,以便我可以更新我的表,而无需挂起程序 - 例如使用subprocess.wait()后跟subprocess.returncode仍然只是粘贴,直到流程完成。我需要一种“当进程完成时,检查退出代码并运行一个更新QTableWidget的函数。”

我确实发现这两个帖子似乎让我朝着正确的方向前进,但是并没有让我在那里:

Understanding Popen.communicate

How to get exit code when using Python subprocess communicate method?

希望这是有道理的。这是我的代码的简化版本,我意识到它是半生半熟的,但是我已经用了一个多小时的时间来解决这个问题,而且我已经忘记了一些事情......

import os, subprocess

ae_app = 'afterfx'
ae_path = os.path.join('C:/Program Files/Adobe/Adobe After Effects CC 2015/Support Files', ae_app + ".exe")
filename = "E:/Programming/Python/Archive tool/talk.jsx"
commandLine = 'afterfx -noui -r ' + filename

processList = [commandLine]
processes = []

for process in processList:
    f = os.tmpfile()
    aeProcess = subprocess.Popen(process, executable=ae_path, stdout=f)
    processes.append((aeProcess, f))

for aeProcess, f in processes:
    # this is where I need serious help...
    aeProcess.wait()
    print "the line is:"
    print aeProcess.returncode
  • 斯潘塞

1 个答案:

答案 0 :(得分:0)

你提到过PyQt,所以你可以使用PyQt的QProcess类。

def start_processes(self, process_list):
    for cmd, args in process_list:
        proc = QProcess(self)
        proc.finished.connect(self.process_finished)
        proc.start(cmd, args)

def process_finished(self, code, status):
    # Do something

更新已添加完整的工作示例。适用于PyQt4和PyQt5(仅切换注释行3并取消注释第4行)

sleeper.py

import sys
from time import sleep
from datetime import datetime as dt

if __name__ == '__main__':
    x = int(sys.argv[1])
    started = dt.now().time()
    sleep(x)
    ended = dt.now().time()
    print('Slept for: {}, started: {}, ended: {}'.format(x, started, ended))
    sys.exit(0)

main.py

import sys

from PyQt5 import QtCore, QtWidgets
# from PyQt4 import QtCore, QtGui as QtWidgets


class App(QtWidgets.QMainWindow):
    cmd = r'python.exe C:\_work\test\sleeper.py {}'

    def __init__(self):
        super(App, self).__init__()
        self.setGeometry(200, 200, 500, 300)
        self.button = QtWidgets.QPushButton('Start processes', self)
        self.button.move(20, 20)
        self.editor = QtWidgets.QTextEdit(self)
        self.editor.setGeometry(20, 60, 460, 200)

        self.button.clicked.connect(self.start_proc)

    def start_proc(self):
        for x in range(5):
            proc = QtCore.QProcess(self)
            proc.finished.connect(self.finished)
            proc.start(self.cmd.format(x))

    def finished(self, code, status):
        self.editor.append(str(self.sender().readAllStandardOutput()))


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    gui = App()
    gui.show()
    app.exec_()