Подтвердить что ты не робот

Subprocess.wait() не ждет завершения процесса Popen (при использовании потоков)?

У меня возникают проблемы при использовании subprocess.Popen(), чтобы вызвать несколько экземпляров одного и того же приложения из моего python script, используя потоки, чтобы они запускались одновременно. В каждом потоке я запускаю приложение с помощью вызова popen(), а затем жду его завершения, вызывая wait(). Проблема заключается в том, что wait() -call фактически не ждет завершения процесса. Я экспериментировал, используя только один поток, и распечатывая текстовые сообщения, когда процесс начинается, и когда он заканчивается. Таким образом, функция потока будет выглядеть примерно так:

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() на самом деле не ждет? У меня есть несколько разных внешних приложений (консольные приложения С++), которые, в свою очередь, будут работать одновременно с несколькими экземплярами, а для некоторых из них работает мой код, а для других - нет. Могут ли быть проблемы с внешними приложениями, которые каким-то образом влияют на вызов wait()? Код для создания потоков выглядит примерно так:

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

Обновление 1: Я также должен добавить, что для некоторых внешних приложений я иногда получаю код возврата (proc.returncode) -1073471801. Например, одно из внешних приложений даст этот код возврата первые два раза Popen, но не последние два (когда у меня есть четыре задания).

Обновление 2: Чтобы прояснить ситуацию, прямо сейчас у меня есть четыре задания в очереди, которые состоят из четырех разных тестовых случаев. Когда я запускаю свой код, для одного из внешних приложений первые два Popen -качества генерируют код возврата -1073471801. Но если я напечатаю точную команду, которая вызывает Popen, и запускает ее в командном окне, она выполняется без каких-либо проблем.

Решено! Мне удалось решить проблемы, которые у меня были. Я думаю, что проблема заключалась в отсутствии опыта в программировании с резьбой. Я пропустил тот факт, что когда я создал свои первые рабочие потоки, они продолжали жить до выхода python script. По ошибке я создавал больше рабочих потоков каждый раз, когда добавляю новые элементы в очередь (я делаю это в партиях для каждой внешней программы, которую я хочу запустить). Таким образом, к тому времени, когда я добрался до четвертого внешнего приложения, у меня было четыре потока одновременно, хотя я только думал, что у меня есть один.

4b9b3361

Ответ 1

Вы также можете использовать check_call() вместо Popen. check_call() ожидает завершения команды, даже когда shell=True и затем возвращает код завершения задания.

Ответ 2

К сожалению, при запуске вашего подпроцесса с помощью shell=True wait() будет ждать завершения подпроцесса sh, а не для команды cmd.

Я предлагаю, если можно не использовать shell=True, если это невозможно, вы можете создать группу процессов, как в этом , и использовать os.waitpid, чтобы ожидать, что группа процессов будет не просто процессом оболочки.

Надеюсь, что это было полезно:)

Ответ 3

Убедитесь, что все приложения, которые вы вызываете, имеют действительные коды возврата системы, когда они завершают

Ответ 4

У меня тоже были проблемы, но я был вдохновлен твоей.

Моя выглядит так и прекрасно работает:

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

Заметьте, что это тоже скрывает окно.