Невозможно полностью остановить подпроцесс в python [duplicate]

Вы можете удалить незаконные символы с помощью Linq следующим образом:

  var invalidChars = Path.GetInvalidFileNameChars ();  var invalidCharsRemoved = stringWithInvalidChars .Where (x = & gt;! invalidChars.Contains (x)) .ToArray ();   

EDIT Вот как он выглядит с требуемым правлением, упомянутым в комментариях:

  var invalidChars = Path.GetInvalidFileNameChars ();  string invalidCharsRemoved = новая строка (stringWithInvalidChars .Where (x = & gt;! invalidChars.Contains (x)) .ToArray ());   
236
задан Piotr Dobrogost 21 October 2012 в 13:48
поделиться

8 ответов

Используйте группу процессов , чтобы включить отправку сигнала ко всему процессу в группах. Для этого вы должны прикрепить session id к родительскому процессу процессов порожденного / дочернего процесса, который является оболочкой в ​​вашем случае. Это сделает его лидером группы процессов. Итак, теперь, когда сигнал отправляется руководителю группы процессов, он передается всем дочерним процессам этой группы.

Вот код:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups
316
ответ дан Imran 16 August 2018 в 01:04
поделиться

Ни один из этих ответов не работал для меня, поэтому я оставил код, который действительно работал. В моем случае даже после убийства процесса с помощью .kill() и получения кода возврата .poll() процесс не завершился.

Следуя документации subprocess.Popen :

"... для правильной очистки хорошо выполненное приложение должно убить дочерний процесс и завершить связь ... »

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

В моем случае я не получил proc.communicate() после вызова proc.kill(). Это очищает процесс stdin, stdout ... и завершает процесс.

3
ответ дан epinal 16 August 2018 в 01:04
поделиться

Я мог бы сделать это с помощью

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

, он убил cmd.exe и программу, для которой я дал команду.

(В Windows)

16
ответ дан jfs 16 August 2018 в 01:04
поделиться

Как сказал Саи, оболочка - это ребенок, поэтому сигналы перехватываются им - лучший способ, который я нашел, - использовать shell = False и использовать shlex для разделения командной строки:

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Затем p.kill () и p.terminate () должны работать так, как вы ожидаете.

4
ответ дан Matt Billenstein 16 August 2018 в 01:04
поделиться
  • 1
    В моем случае это действительно не помогает, учитывая, что cmd является «cd path & amp; & amp; zsync и т. д. & quot ;. Так что на самом деле команда не работает! – user175259 26 January 2011 в 00:00
  • 2
    Используйте абсолютные пути вместо изменения каталогов ... Опционально os.chdir (...) в этот каталог ... – Matt Billenstein 26 January 2011 в 07:27
  • 3
    Встроенная функция изменения рабочего каталога дочернего процесса. Просто передайте аргумент cwd в Popen . – Jonathon Reinhart 17 August 2015 в 01:22
  • 4
    Я использовал shlex, но проблема все еще сохраняется, kill не убивает дочерние процессы. – hungryWolf 25 January 2017 в 06:46

Если вы можете использовать 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)
32
ответ дан Remco Haszing 16 August 2018 в 01:04
поделиться
  • 1
    Это закончило работать для меня в Windows. – benjammin 4 February 2015 в 22:30
  • 2
    AttributeError: 'Process' object has no attribute 'get_children для pip install psutil. – d33tah 13 July 2015 в 21:47
  • 3
    Я думаю, get_children () должен быть child (). Но в Windows это не сработало, процесс все еще существует. – Godsmith 18 September 2015 в 12:51
  • 4
    @Godsmith - API psutil изменился, и вы правы: children () делает то же, что и get_children (). Если он не работает в Windows, возможно, вы захотите создать ошибку в GitHub – Jovik 22 September 2015 в 14:20

Когда shell=True оболочка является дочерним процессом, а командами являются ее дочерние элементы. Таким образом, любые SIGTERM или SIGKILL будут убивать оболочку, но не ее дочерние процессы, и я не помню хороший способ сделать это. Лучший способ, который я могу придумать, - использовать shell=False, иначе, если вы убьете процесс родительской оболочки, он оставит процесс с отсутствующей оболочкой.

7
ответ дан sjs 16 August 2018 в 01:04
поделиться
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() должен работать.

Я не знаю, какое влияние это будет на вашу трубу.

74
ответ дан slayton 16 August 2018 в 01:04
поделиться
  • 1
    Это работает в Windows и MAC. – speedyrazor 21 May 2014 в 15:43
  • 2
    Хорошее и легкое решение для * nix, спасибо! Работы на Linux, также должны работать и для Mac. – MarSoft 24 August 2015 в 14:10
  • 3
    Очень приятное решение. Если ваш cmd оказывается оболочкой сценария оболочки для чего-то другого, вызовите окончательный двоичный код там с помощью exec, чтобы иметь только один подпроцесс. – Nicolinux 4 August 2016 в 17:51
  • 4
    Это прекрасно. Я пытался выяснить, как порождать и убивать подпроцесс на рабочее пространство на Ubuntu. Этот ответ мне помог. Жаль, что я не смог бы его увеличить – Sergiy Kolodyazhnyy 25 August 2016 в 03:35
  • 5
    это не работает, если в cmd используется двоеточие – gnr 2 December 2017 в 00:34
0
ответ дан Zx4161 29 October 2018 в 07:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: