Как убить процесс Popen(‘start’, shell=True)
@YaroslavSurzhikov: сигналы на Windows весьма ограничены. os.killpg не поддерживается (можно попробовать послать процессам из той же консоли сигнал ( start новое окно открывает): os.kill(pid, signal.CTRL_C_EVENT) (не тестировал)), хотя если taskkill не помогает, то нужно больше подробностей.
28 окт 2017 в 19:39
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Методы .terminate() , .kill() у subprocess.Popen пытаются остановить только сам процесс:
#!/usr/bin/env python3 import subprocess import sys import time start = time.monotonic() process = subprocess.Popen([sys.executable or 'python', '-c', 'import time; time.sleep(30)']) assert process.poll() is None # process is alive process.terminate() process.wait() assert (time.monotonic() - start) < 30 # exited before timeout assert process.poll() is not None # process is dead and reaped
При этом дочерние процессы могут продолжать жить, пример.
Вызвав Popen() с shell=True параметром, создаётся неявно процесс ( cmd.exe , /bin/sh ), который запускает переданную команду. Если это не встроенная/внутренняя команда, то у вас как минимум два процесса получается (сама оболочка плюс программа, которую она запустила). .kill() убивает саму оболочку, при этом дочерний процесс может продолжить жить. На *nix в этом случае можно попробовать запускать процесс в отдельной группе процессов и затем послать сигнал этой группе, чтобы все процессы завершились (похоже на то как Ctrl+C в баше работает): How to terminate a python subprocess launched with shell=True. На Windows, можно taskkill попробовать:
from subprocess import Popen, check_call process = Popen('py -c "import time; time.sleep(30)"', shell=True) check_call("TASKKILL /F /PID /T".format(pid=process.pid))
/T аргумент говорит, что taskkill пытается убить как сам процесс так и любые дочерние процессы, которые он запустил. Используя /IM параметр, можно по имени процессы остановить.
Чтобы закрыть новое окно, созданное start командой, по завершению дочерней команды, можно явно /c параметр передать для cmd :
D:\> start /wait "title" cmd /c batch.cmd
Можно добавить /B к start , чтобы не создавалось новое окно. Если вы использовали start, чтобы в фоне, что-то выполнить, то в Питоне этого не нужно, просто уберите start ( Popen() вызов не ждёт пока процесс завершится). Аналогично, если вам не нужно внутреннюю команду запустить, то можно без shell=True обойтись как правило.
В качестве альтернативы явной остановки, можно запустить процессы таким образом, чтобы дочерние процессы автоматически уничтожались, когда родитель завершается: Python: how to kill child process(es) when parent dies? На Windows, это можно организовать присваиванием созданного родительского процесса к своему Job объекту.
Как завершить процесс в python?
Добрый день.
Суть в том, что запускаю ffmpeg с помощью subprocess.Popen, и когда завершаю работу скрипта с помощью proc.kill() затем proc.terminate() затем sys.exit() , то ffmpeg продолжает висеть в диспетчере задач, хоть и не активен (т.е в столбике где написано ЦП показывает 0 ). Как убрать его полностью из диспетчера задач?
- Вопрос задан более трёх лет назад
- 8779 просмотров
Комментировать
Решения вопроса 1
WorldEn @WorldEn Автор вопроса
Решил проблему с помощью библиотеки psutil
import psutil parent_pid = 30437 # my example parent = psutil.Process(parent_pid) for child in parent.children(recursive=True): # or parent.children() for recursive=False child.kill() parent.kill()
Ответ написан более трёх лет назад
Комментировать
Нравится 3 Комментировать
Ответы на вопрос 1
Вероятно ffmpeg запускает подпроцессы. Убивайте всю группу:
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid) os.killpg(os.getpgid(pro.pid), signal.SIGTERM)
Ответ написан более трёх лет назад
WorldEn @WorldEn Автор вопроса
os.getpgid это для линукса, а у меня винда. Есть аналог этой команды для моей ОС ?))
Ваш ответ на вопрос
Войдите, чтобы написать ответ
- Python
Как сгенерировать случайное имя файла?
- 1 подписчик
- час назад
- 38 просмотров

- Python
Когда запускаю клиента вылетает из всех устройств?
- 1 подписчик
- 6 часов назад
- 43 просмотра
Закрытая программа остаётся в процессах
После сборки скрипта в exe с помощью pyinstaller я закрываю получившуюся программу, но она остаётся в процессах и её можно закрыть уже через диспетчер задач.
pyinstaller -F -w -i=D:/icon.ico D:/keywords_and_sites.py
Отслеживать
9,663 9 9 золотых знаков 24 24 серебряных знака 35 35 бронзовых знаков
задан 19 фев 2020 в 20:38
394 1 1 золотой знак 3 3 серебряных знака 13 13 бронзовых знаков
покажите как вы обрабатывете выход
19 фев 2020 в 20:41
pyinstaller -F -w -i=D:/icon.ico D:/keywords_and_sites.py
19 фев 2020 в 21:00
Я про код который отрабатывется внутри прргаммы при закрытии.
19 фев 2020 в 21:04
Код достаточно объёмный. Это парсер, в котором есть строка threading.Thread(target=progress).start(), которая способствует работе прогрессбара. Я думаю, что она может мешать полноценному закрытию программы
19 фев 2020 в 21:08
Ну так вот напишите минимальный пример, когда проблема воспроизводится. Скорее всего либо обратно не вызываете join() , либо в самой ветке нет условия выхода. Опять же не забывайте про флаг daemon .
Как скрыть консоль процесса из python программы?
Есть gui приложение на python, в котором я запускаю процесс шахматного движка, используя библиотеку python chess library, запускаю командой:
engine = chess.engine.SimpleEngine.popen_uci("H:/stockfish_9_x64.exe")
Затем я собрал exe из исходников на python, проблема в том, что когда запускается процесс движка, появляется его консоль. Вопрос: как сделать, чтобы она не появлялась? Как я понимаю, нужно узнать PID этого процесса (по его имени), а затем, используя его, скрыть консоль. Не подскажите, как это проще всего сделать? Заранее спасибо.
