2014-02-25 246 views
2

這是我第一次發佈到社區,但我通過搜索大約2周的時間就可以學到我所能做的。我似乎遇到了一個死路,我似乎無法通過反覆試驗或通過閱讀別人的帖子來找到答案。殺死Popen子進程

我現在要做的就是殺死由Popen和shell本身創建的進程。我必須補充一點,我是編程新手,這是我第一個「真正的」世界任務。

我見過的解決方案說創建一個組ID,但這是爲Unix和我在Windows上。 Popen.kill()和Popen.terminate()不會殺死shell的孩子。由此代碼啓動的程序不會退出,它的PID與shell的PID不同。我願意接受這些建議,因爲我將它作爲一種學習工具和一些具有生產力的工具。其他一些解決方案並沒有殺死這個進程。我可以通過DOS和Python解釋器殺死它,但是我必須手動從TASKLIST中查找PID,然後鍵入它。我需要從此程序中將其殺死。

我構建此代碼以保存讀取excel文檔值的MathCad模板的多個文檔,並用新文件名吐出保存的文檔。提前致謝。請原諒你可能看到的任何新手編碼的東西,因爲我只是想讓自己的腳溼潤。

嘗試其他任務和更新(2014年2月26日):

試圖殺死使用subprocess.call程序('TASKKILL ...)代替subprocess.Popen。它不會殺死shell創建的子項。嘗試用subprocess.call('....',shell = True)替換proc = subprocess.Popen('....'shell = True)並且SendKeys函數不再起作用。使用kill_proc_tree函數嘗試了psutil函數,並使用「EOFError:[WinError 10054]現有連接被遠程主機強制關閉」彈出窗口。孩子計劃仍然沒有關閉。

如果我刪除kill/terminate/close命令並讓程序運行,則proc.pid與os.getpid()不同。如果我使用psutil.Process(proc.pid) - 它表示當Python解釋器將返回其PID時,該進程不存在。如果我得到MathCadPrime.exe PID =例如1111從TASKLIST和使用psutil.Process(1111).parent,它沒有顯示父母。這可能是爲什麼在shell上執行TASKKILL不會關閉子項的原因?我已經發布了我的代碼,完全按照我寫的代碼來查看你的專家是否看到我沒有看到的東西。

#def kill_proc_tree(pid, including_parent=True): 
# parent = psutil.Process(pid) 
# for child in parent.get_children(recursive=True): 
#  child.kill() 
# if including_parent: 
#  parent.kill() 

import subprocess 
import win32api 
import win32com.client 
import time 
import os 
import signal 
import psutil 

# User files 
file = "C:\Directory\SubDirectory\file.mcdx" 


# Command line function 
# /B /D - No command line window or explorer window  
proc = subprocess.Popen('start /B /D           \ 
     "C:\Program Files\PTC\Mathcad\Mathcad Prime 2.0\" "MathcadPrime.exe" \ 
     "C:\Directory\SubDirectory\file.mcdx"', shell=True) 

# Set and test for active window 
    focus = False 
    while (focus == False): 
      focus = shell.AppActivate("MathCad Prime 2.0 - " + file) 
      time.sleep(1) 
      if (focus == True): 
       break 

# Send MathCad Prime commands 
shell.SendKeys('%', 0) 
time.sleep(0.5) 
shell.SendKeys('c', 0) 
time.sleep(0.1) 
shell.SendKeys('c', 0) 
time.sleep(2.0) 
shell.SendKeys('%', 0) 
time.sleep(0.5) 
shell.SendKeys('f', 0) 
time.sleep(0.1) 
shell.SendKeys('s', 0) 
time.sleep(4.0) 



#Other methods to tried to kill children: 

#Method 1: 
#subprocess.call("TASKKILL /F /T /PID {pid}".format(pid=proc.pid)) 

#Method 2: 
#subprocess.Popen("TASKKILL /F /T /PID {pid}".format(pid=proc.pid)) 

#Method 3: 
#if (int(proc.pid) > 0): 
# os.kill(proc.pid, signal.SIGTERM) 

#Method 4 (used with kill_proc_tree): 
#proc1 = os.getpid() 
#kill_proc_tree(proc1) 
+1

你有[閱讀文檔](http://docs.python.org/2/library/subprocess.html#subprocess.Popen.terminate)嗎? – mhlester

+1

是的。 Popen.kill()和Popen.terminate()不會殺死shell的孩子。由此代碼啓動的程序不會退出,它的PID與shell的PID不同。 –

+0

好的謝謝澄清 – mhlester

回答

3

謝謝你們所有的幫助,你們幫助我得出結論。與建議略有不同,但每次都能完成工作。我在家裏,而不是在工作(所以我把它寫在我的頭頂上),但基本上我所做的只是將TASKLIST寫入文本文件並過濾掉一串代碼:

os.chdir('C:\Code') 
subprocess.call('TASKLIST /fi "IMAGENAME eq MathcadPrime.exe" /nh /fo csv > task.txt) 

然後分析出PID:

doc = open('task.txt', 'rt') 
parse = doc.read() 
listing = parse.split(",") 
PID = listing[1] 
PID = int(PID.replace('"','').replace("'","")) 
os.kill(PID, signal.SIGTERM) 

我希望這可以幫助別人。

+0

注意:它殺死了一個名爲'「MathcadPrime.exe」(Unix上的'pkill processname'類似物)的進程。這與殺死進程樹是一個不同的問題。如果'MathcadPrime.exe'也會讓子進程在後面被殺掉,你會怎麼做? – jfs

+0

@ J.F.Sebastian好的問題J.F.,因爲我不知道。我不相信Mathcad以我使用它的方式產生其他進程。這是一個簡單的開放,做幾個進程,然後保存/關閉。我非常樂於接受使代碼更緊密的解決方案。我會試圖殺死整個進程樹,但我不知道如何解決我之前公佈的問題。 –

+1

['基於psutil'的解決方案](http://stackoverflow.com/questions/22021701/kill-the-popen-child-process?noredirect=1#comment33387964_22021701)應該工作。 – jfs

2

我嘗試下面的代碼,它的工作對我來說:

import subprocess 
import os,signal 
proc = subprocess.Popen('dir /S', shell=True) 
if (int(proc.pid) > 0): 
    print "killing ",proc.pid 
    print os.kill(proc.pid, signal.SIGTERM) 

而且我所觀察到的是,如果從POPEN啓動的程序響應「CTRL + C」,你可以用信號.CTRL_C_EVENT關閉程序。如果啓動的程序不響應該事件,則必須手動關閉它。我想,我的上面的代碼工作,因爲cmd.exe響應該事件。

+0

我得到「[WinError5]訪問被拒絕」錯誤。不知道是否與我公司的管理權限或其他。我將不得不做更多的研究並回到你身邊,我會在家試着告訴我有關管理員權利的信息。 –

+0

你也可以試試SIGKILL。您可以通過嘗試殺死python之外的進程來確定您的用戶帳戶是否有特權。 – amos

+0

@ user3感謝您的幫助 –