Ответ 1
Вы также можете использовать check_call()
вместо Popen. check_call()
ожидает завершения команды, даже когда shell=True
и затем возвращает код завершения задания.
У меня возникают проблемы при использовании 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. По ошибке я создавал больше рабочих потоков каждый раз, когда добавляю новые элементы в очередь (я делаю это в партиях для каждой внешней программы, которую я хочу запустить). Таким образом, к тому времени, когда я добрался до четвертого внешнего приложения, у меня было четыре потока одновременно, хотя я только думал, что у меня есть один.
Вы также можете использовать check_call()
вместо Popen. check_call()
ожидает завершения команды, даже когда shell=True
и затем возвращает код завершения задания.
К сожалению, при запуске вашего подпроцесса с помощью shell=True
wait(
) будет ждать завершения подпроцесса sh
, а не для команды cmd
.
Я предлагаю, если можно не использовать shell=True
, если это невозможно, вы можете создать группу процессов, как в этом , и использовать os.waitpid, чтобы ожидать, что группа процессов будет не просто процессом оболочки.
Надеюсь, что это было полезно:)
Убедитесь, что все приложения, которые вы вызываете, имеют действительные коды возврата системы, когда они завершают
У меня тоже были проблемы, но я был вдохновлен твоей.
Моя выглядит так и прекрасно работает:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
proc = subprocess.Popen(command, startupinfo=startupinfo)
proc.communicate()
proc.wait()
Заметьте, что это тоже скрывает окно.