Вот код Python для запуска произвольной команды, возвращающей свои stdout
данные, или для создания исключения для ненулевых кодов выхода:
proc = subprocess.Popen(
cmd,
stderr=subprocess.STDOUT, # Merge stdout and stderr
stdout=subprocess.PIPE,
shell=True)
communicate
используется для ожидания завершения процесса:
stdoutdata, stderrdata = proc.communicate()
subprocess
Модуль не поддерживает тайм - аута - способность убивать процесс , протекающий в течение более чем X количества секунд - таким образом, communicate
может длиться вечно бежать.
Как проще всего реализовать таймауты в программе на Python, предназначенной для работы в Windows и Linux?
python
multithreading
timeout
subprocess
Шридхар Ратнакумар
источник
источник
Ответы:
В Python 3.3+:
output
является байтовой строкой, которая содержит объединенную команду stdout, данные stderr.check_output
повышаетCalledProcessError
ненулевой статус выхода, как указано в тексте вопроса, в отличие отproc.communicate()
метода.Я удалил,
shell=True
потому что это часто используется без необходимости. Вы всегда можете добавить его обратно, если этоcmd
действительно необходимо. Если вы добавитеshell=True
ie, если дочерний процесс порождает своих потомков;check_output()
может вернуться намного позже, чем указывает время ожидания, см. Ошибка таймаута подпроцесса .Функция тайм-аута доступна в Python 2.x через
subprocess32
обратный порт модуля 3.2+ подпроцесса.источник
check_output()
- это предпочтительный способ получения вывода (он возвращает результат напрямую, не игнорирует ошибки, он доступен всегда). 2run()
- более гибкий, ноrun()
игнорирует ошибку по умолчанию и требует дополнительных шагов для получения выходных данных 3check_output()
- реализован в терминахrun()
и, следовательно, принимает большинство одинаковых аргументов. 4 нит:capture_output
доступен начиная с 3,7, а не 3,5Я не знаю много о деталях низкого уровня; но, учитывая, что в python 2.6 API предлагает возможность ожидания потоков и завершения процессов, как насчет запуска процесса в отдельном потоке?
Вывод этого фрагмента в моей машине:
где видно, что при первом выполнении процесс завершился правильно (код возврата 0), а во втором - процесс был прерван (код возврата -15).
Я не проверял в Windows; но, помимо обновления примера команды, я думаю, что она должна работать, так как я не нашел в документации ничего, что говорило бы о том, что thread.join или process.terminate не поддерживаются.
источник
Ответ jcollado может быть упрощен с помощью класса threading.Timer :
источник
lambda
:t = Timer(timeout, proc.kill)
timer.isAlive()
beforetimer.cancel()
означает, что все закончилось нормальноЕсли вы на Unix,
источник
Вот решение Алекса Мартелли как модуля с правильным процессом убийства. Другие подходы не работают, потому что они не используют proc.communicate (). Поэтому, если у вас есть процесс, который производит много выходных данных, он заполнит свой выходной буфер и затем заблокируется, пока вы не прочитаете что-то из него.
источник
ValueError: signal only works in main thread
Я изменил ответ sussudio . Теперь функция возвращает: (
returncode
,stdout
,stderr
,timeout
) -stdout
иstderr
декодируется для UTF-8 строкиисточник
удивил, что никто не упомянул использование
timeout
timeout 5 ping -c 3 somehost
Очевидно, что это не подходит для каждого варианта использования, но если вы работаете с простым сценарием, это трудно победить.
Также доступно как gtimeout в coreutils через
homebrew
для пользователей Mac.источник
proc = subprocess.Popen(['/usr/bin/timeout', str(timeout)] + cmd, ...)
. Есть лиtimeout
команда на Windows, как спрашивает OP?timeout
теперь поддерживается с помощьюcall()
иcommunicate()
в модуле подпроцесса (по состоянию на Python3.3):Это вызовет команду и вызовет исключение
если команда не заканчивается через 20 секунд.
Затем вы можете обработать исключение, чтобы продолжить ваш код, например:
Надеюсь это поможет.
источник
timeout
параметр . Хотя упоминание об этом еще раз не повредит.Другой вариант - записать во временный файл, чтобы предотвратить блокировку stdout вместо необходимости опроса с connect (). Это сработало для меня, где другие ответы не сделали; например на окнах.
источник
Я не знаю , почему это не так , но упоминался Python 3.5, есть новая
subprocess.run
универсальная команда (которая предназначена для заменыcheck_call
,check_output
...) и который имеетtimeout
параметр , а также.Возникает
subprocess.TimeoutExpired
исключение по истечении времени ожидания.источник
Вот мое решение, я использовал Thread и Event:
В действии:
источник
Решением, которое я использую, является префикс команды оболочки с ограничением по времени . Если команда занимает слишком много времени, timelimit остановит его, и Popen получит код возврата, установленный timelimit. Если это> 128, это означает, что ограничение по времени убило процесс.
Смотрите также подпроцесс python с тайм-аутом и большим выводом (> 64 КБ)
источник
timeout
- packages.ubuntu.com/search?keywords=timeout - но ни один из них не работает в Windows, не так ли?Я добавил решение с многопоточностью
jcollado
в мой модуль Python easyprocess .Установка:
Пример:
источник
если вы используете Python 2, попробуйте
источник
Добавление команды Linux
timeout
не является плохим решением проблемы, и оно сработало для меня.источник
Я реализовал то, что я мог собрать из нескольких из них. Это работает в Windows, и так как это вики сообщества, я думаю, я бы тоже поделился своим кодом:
Затем из другого класса или файла:
источник
terminate()
Функция отмечает поток прекращенным, но фактически не прекращается поток! Я могу проверить это в * nix, но у меня нет компьютера с Windows для тестирования.Когда вы поймете, что весь процесс работает в * unix, вы легко найдете более простое решение:
Рассмотрим этот простой пример того, как сделать методу timeabletable connect () meth с помощью select.select () (в настоящее время доступно почти все на * nix). Это также можно записать с помощью epoll / poll / kqueue, но вариант select.select () может быть хорошим примером для вас. И основные ограничения select.select () (скорость и 1024 макс. Fds) не применимы для вашей задачи.
Это работает под * nix, не создает потоков, не использует сигналы, может быть запущено из любого потока (не только основного), и достаточно быстро для чтения 250 Мбит / с данных со стандартного выхода на моей машине (i5 2.3 ГГц).
Существует проблема в присоединении stdout / stderr в конце связи. Если у вас огромный вывод программы, это может привести к большому использованию памяти. Но вы можете позвонить общаться () несколько раз с меньшими тайм-аутами.
источник
Вы можете сделать это используя
select
источник
Я успешно использовал killableprocess в Windows, Linux и Mac. Если вы используете Cygwin Python, вам понадобится версия killableprocess OSAF, потому что в противном случае родные процессы Windows не будут уничтожены.
источник
Хотя я не смотрел на это широко, это декоратор, который я нашел в ActiveState, кажется весьма полезным для такого рода вещей. Вместе с тем
subprocess.Popen(..., close_fds=True)
, по крайней мере, я готов к написанию сценариев в Python.источник
Это решение убивает дерево процессов в случае shell = True, передает параметры процессу (или нет), имеет тайм-аут и получает выходные данные stdout, stderr и процесса обратного вызова (он использует psutil для kill_proc_tree). Это было основано на нескольких решениях, опубликованных в SO, включая Jcollado. Публикация в ответ на комментарии Ансона и Храдице в ответе jcollado. Протестировано в Windows Srvr 2012 и Ubuntu 14.04. Обратите внимание, что для Ubuntu вам нужно изменить вызов parent.children (...) на parent.get_children (...).
источник
Есть идея создать подкласс класса Popen и расширить его с помощью некоторых простых декораторов методов. Давайте назовем это ExpurablePopen.
источник
У меня была проблема с тем, что я хотел завершить многопоточный подпроцесс, если это заняло больше времени, чем заданное время ожидания. Я хотел установить время ожидания
Popen()
, но оно не сработало. Затем я понял, чтоPopen().wait()
он равен,call()
и у меня возникла идея установить тайм-аут в.wait(timeout=xxx)
методе, который наконец заработал. Таким образом, я решил это так:источник
К сожалению, я обязан очень строгими правилами раскрытия исходного кода моим работодателем, поэтому я не могу предоставить настоящий код. Но, на мой вкус, лучшее решение - создать подкласс, переопределяющий
Popen.wait()
опрос, а не ждать бесконечно, иPopen.__init__
принять параметр тайм-аута. Как только вы это сделаете, все остальныеPopen
методы (которые вызываютwait
) будут работать, как ожидается, в том числеcommunicate
.источник
https://pypi.python.org/pypi/python-subprocess2 предоставляет расширения для модуля подпроцесса, которые позволяют ждать до определенного периода времени, в противном случае прерываются.
Итак, чтобы подождать до 10 секунд до завершения процесса, в противном случае убейте:
Это совместимо как с Windows, так и с Unix. «results» - это словарь, он содержит «returnCode», который является возвратом приложения (или «None», если его нужно было убить), а также «actionTaken». который будет "SUBPROCESS2_PROCESS_COMPLETED", если процесс завершен нормально, или маской "SUBPROCESS2_PROCESS_TERMINATED" и SUBPROCESS2_PROCESS_KILLED в зависимости от предпринятых действий (подробности см. в документации)
источник
для python 2.6+ используйте gevent
источник
Python 2.7
источник
источник
Просто пытался написать что-то попроще.
источник