Я запускаю подпроцесс следующей командой:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
Однако, когда я пытаюсь его завершить, используя:
p.terminate()
или же:
p.kill()
к оманда продолжает работать в фоновом режиме, поэтому мне было интересно, как я могу завершить процесс.
Обратите внимание, что , когда я запускаю команду с:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
о н действительно завершается успешно при вызове p.terminate() .
Ответ 1
Используйте группу процессов, чтобы разрешить отправку сигнала всем процессам в группах. Для этого вы должны прикрепить идентификатор сеанса к родительскому процессу порожденных/дочерних процессов, который в вашем случае является оболочкой. Это сделает его лидером группы процессов. Итак, теперь, когда сигнал отправляется лидеру группы процессов, он передается всем дочерним процессам этой группы.
Вот код:
import os
Почему PYTHON такой Медленный? Причины Низкой Производительности
import signal
import subprocess
# Команда os.setsid() передается в аргументе preexec_fn, поэтому.
# она выполняется после fork() и перед exec() для запуска оболочки.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
os.killpg(os.getpgid(pro.pid), signal.SIGTERM) # Отправляет сигнал всем группам процессов
Ответ 2
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()
p.kill() заканчивает выполнение и завершает процесс оболочки, но cmd все еще работает.
Я нашел удобное решение:
p = subprocess.Popen(«exec » + cmd, stdout=subprocess.PIPE, shell=True)
Это заставит cmd унаследовать процесс оболочки вместо того, чтобы оболочка запускала дочерний процесс, который не завершается. p.pid тогда будет идентификатором вашего процесса cmd, и p.kill() должен сработать.
Ответ 3
Если вы можете использовать psutil, это отлично работает:
import subprocess
import psutil
def kill(proc_pid):
process = psutil.Process(proc_pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
proc = subprocess.Popen([«infinite_app», «param»], shell=True)
try:
proc.wait(timeout=3)
except subprocess.TimeoutExpired:
kill(proc.pid)
Ответ 4
Я мог бы сделать это, используя:
from subprocess import Popen
process = Popen(command, shell=True)
Popen(«TASKKILL /F /PID /T».format(pid=process.pid))
Это завершает cmd.exe программу, для которой дается эта команда ( в Windows).
Ответ 5
Ни один из ответов у меня не сработал, поэтому я даю код, который действительно работает. В моем случае даже после завершения процесса .kill() и получения .poll() кода возврата, процесс не завершился.
Следуя subprocess.Popen из документации :
«. для правильной очистки приложение с допустимым поведением должно завершить дочерний процесс и завершить обмен данными . »
Python-джедай #7 — Циклы
proc = subprocess.Popen(. )
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
В моем случае мне не хватало proc.communicate() после вызова proc.kill() . Это очищает процесс stdin, stdout . и завершает процесс.
Мягкая остановка скрипта на python по Ctrl+C
Под мягкой или безопасной остановкой скрипта понимается такой процесс прерывания, при котором программа «узнает» что её останавливают и запускает часть кода необходимую для корректного завершения программы. Часто такую остановку называют Graceful Exit или Graceful Kill.
Такое поведение может быть полезно например в случае, когда идёт какой-нибудь расчет и требуется приостановить выполнение с возможностью в дальнейшем запустить продолжение из текущей точки останова. Тогда после поступления сигнала на мягкую остановку данные из оперативной памяти не теряются, а записываются на жесткий диск.
Однако более частое применение — это мягкая остановка цикла, когда необходимо перед выходом из программы довести вычисления до логического конца, т.е. полностью закончить текущую итерацию.
Пример Graceful остановки скрипта в цикле:
import signal import time class GracefulKiller: kill_now = False def __init__(self): signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully) def exit_gracefully(self,signum, frame): self.kill_now = True # инициализируем «улавливателя» сигналов killer = GracefulKiller() # начинаем вычисления, здесь также может быть альтернативный цикл while True: time.sleep(1) print(«doing something in a loop . «) if killer.kill_now: break print «Безопасная остановка успешно заверешена!»
Здесь мы используем два типа сигнала, SIGTERM и SIGINT позволяющие охватить пожалуй все случаи мягкого прерывания.
SIGTERM это основной сигнал, который подает операционная система linux для остановки программы. В отличии от SIGKILL сигнал может быть заблокирован, обработан или же проигнорирован. По умолчанию утилита kill отправляет именно сигнал SIGTERM. Для знакомых с программой htop, попробуйте нажать F9 (kill) и по умолчанию будет выбран именно сигнал -15 SIGTERM, так что это пожалуй самый распространенный способ сказать программе «по доброму» — останавливайся.
Сигнал SIGINT отслеживает остановку процесса пользователем из командной строки, обычно он возникает по Ctrl+с.
Вообще разных сигналов гораздо больше чем SIGTERM и SIGINT, подразделются они на 3 основных класса. Пользовательские (отправляемые пользователем), системные (от ядра системы) и как бы их назвать «программные» (отправляемые другими программами). Возможно для вашей задачи надо будет отлавливать ещё что-то, но 99.9% должно хватить скрипта сверху
Источник: zabaykin.ru
Завершение работы скрипта Python
Я в курсе die() команда в PHP, которая рано останавливает скрипт.
Как я могу это сделать в Python?
автор: Lightness Races in Orbit
10 ответов
import sys sys.exit()
sys.exit([arg])
выход из Python. Это осуществляется путем повышения SystemExit исключение, поэтому действия очистки, указанные в предложениях finally из try заявления соблюдаются, и можно перехватить попытка выхода на внешнем уровне.
необязательный аргумент arg может быть целым числом, дающим статус выхода (значение по умолчанию равно нулю) или другой тип объекта. Если это целое число, ноль считается «успешным завершением», и любое ненулевое значение считается «ненормальным окончание» снарядами и тому подобное. Большинство систем требовать, чтобы он находился в диапазоне 0-127, и давать неопределенные результаты иначе. В некоторых системах существует соглашение о присвоении конкретных значения для конкретных кодов выхода, но это, как правило, недоразвитые; программы Unix обычно используют 2 для синтаксиса командной строки ошибки и 1 для всех других видов ошибок. Если другой тип объекта передается, None эквивалентно передаче нуля, а любой другой объект напечатано на stderr и приводит к коду выхода 1. Особенно, sys.exit(«some error message») быстрый способ выхода из программы, когда возникает ошибка.
С exit() в конечном счете» только » вызывает исключение, оно будет только выходить процесс при вызове из основного потока, и исключение не является перехваченный.
простой способ завершить скрипт Python раньше-использовать встроенную функцию quit (). Нет необходимости импортировать какую-либо библиотеку, и это эффективно и просто.
#do stuff if this == that: quit()
Источник: askdev.ru