2015-06-16 3 views
0

У меня есть простой скрипт, который вызывает другой скрипт python в качестве подпроцесса. Я могу подтвердить, что подпроцесс запущен, и я могу захватить его PID.Python: Завершить подпроцесс = Успех, но он все еще работает (?)

Когда я пытаюсь завершить подпроцесс (в win), я получаю сообщение SUCCESS против правильного идентификатора PID, но диспетчер задач Windows показывает, что 2-й процесс python.exe все еще работает.

Любые предложения для выполнения этой задачи в Win? Я буду простирающимся это работать в OSX и Linux в конце концов:

Упрощенный:

#!/usr/bin/env python 

import os, sys 
import subprocess 
from subprocess import Popen, PIPE, STDOUT, check_call 

pyTivoPath="c:\pyTivo\pyTivo.py" 

print "\nmyPID: %d" % os.getpid() 

## Start pyTivo ## 
py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT) 
print "newPID: %s" % py_process.pid 

## Terminate pyTivo ## 
#py_process.terminate() - for nonWin (?) 
py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f") 

raw_input("\nPress Enter to continue...") 

Примечания: требуется python2.7, эти утилиты не указано

+0

Что случилось с 'Popen.terminate'? s он делает соответствующий вызов win api в Windows. – Dunes

+0

Я заметил, что при запуске subprocess.Popen создаются два процесса. «cmd.exe» и «python.exe». PID, который я получаю от py_process.pid, указывает на «cmd.exe». Я только завершаю «cmd.exe» в своем скрипте. Непонятно, как также захватить PID для «python.exe». –

+0

Всё: python.exe - это ребенок cmd.exe. Я добавил переключатель «/ T» в мою команду TASKKILL, и это также убивает процесс python.exe! –

ответ

1

Два процесса создаются из-за того, что вы вызываете Popen с помощью shell=True. Похоже, единственная причина, по которой вам нужно использовать оболочку, заключается в том, что вы используете ассоциацию файлов с интерпретатором. Для решения проблемы вы также можете попробовать:

from subprocess Popen, PIPE, STDOUT 

pyTivoPath = "c:\pyTivo\pyTivo.py" 
cmd = r'c:\Python27\python.exe "{}"'.format(pyTivoPath) 

# start process 
py_process = Popen(cmd, stdout=PIPE, stderr=STDOUT) 

# kill process 
py_process.terminate() 
+0

Да, все. Я не был понятен синтаксис. - Спасибо! –

1

Используйте /F (Force) включается TASKKILL. Множество оконных команд не имеет полезных возвращаемых значений. Не помните, если TASKKILL возвращает полезное значение.


К сожалению, упускать из виду ваш /F

Вы можете попробовать вызов Win32 API напрямую.

import win32api 
win32api.TerminateProcess(int(process._handle), -1) 

Найденный ActiveState page для этого. Документирует несколько методов уничтожения, включая описанный выше метод Win32.

Существует также ряд причин, по которым Windows не позволит вам завершить процесс. Общими причинами являются разрешения и драйверы с ошибкой, которые имеют ожидающие запросы ввода-вывода, которые не реагируют на сигнал об ошибке.

Существуют некоторые программы, например. ProcessHacker, которые с большим энтузиазмом относятся к процессам убийства, но я не знаю технических деталей наверняка, хотя я подозреваю принудительное закрытие открытых файлов и т. Д., А затем задействован вызов Terminate.

У вас могут быть подобные проблемы в Linux, то есть нет разрешения на уничтожение процесса, или процесс игнорирует сигнал kill. Легче разрешать на Linux, хотя, если kill -9 не работает, его нельзя убить и это более редкое условие, потому что вы должны явно игнорировать сигнал 9 в своем коде.


0) Вы можете использовать TASKKILL /T убить CMD и интерпретатор Python.

1) Если вы изменили процесс создания, чтобы создать процесс python напрямую (вместо того, чтобы запускать .py и полагаться на cmd для запуска) с именем сценария в качестве аргумента команды, вы получите PID, который вы ожидаете, когда создаете обработать.

2) Вы можете использовать TASKKILL /IM, чтобы убить процесс по имени, но имя будет интерпретатором python и может убить непреднамеренные процессы.

+0

Спасибо, Гэри, у меня есть переключатель/F, примененный в TASKKILL. Не повезло. –

+0

Добавить Win32 Api Call –

+0

Гэри, добавил вызов win32api, но увидит тот же результат. Процесс все еще работает. Хм. –

1

В моей реализации следующее фактически создает ДВА процесса в Windows («cmd.exe» и «python.exe»).

py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT) 

Отметить «python.EXE»процесс является дочерним„cmd.exe“процесса, я добавил„/ Т“(дерево) убить переключатель в моей Taskkill:

py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f /t") 

Это приводит к желаемому эффекту, чтобы эффективно убить питона подпроцесс .

Смежные вопросы