2011-10-31 34 views
1

我有一個腳本,它反覆運行一個Ant構建文件並將輸出轉換爲可解析格式。當我使用Popen創建子進程時,有一個很小的時間窗口,點擊Ctrl + C將會終止腳本,但不會終止運行Ant的子進程,從而將打印輸出的殭屍留給只能使用任務終止的控制檯經理。一旦Ant開始打印輸出,點擊Ctrl + C將永遠殺死我的腳本以及Ant。有沒有辦法讓它按Ctrl + C總是會殺死運行Ant的子進程而不會留下殭屍?在Python 2.5上可靠地終止子進程

另外值得注意的是:我有一個SIGINT處理程序,它在調用exit(0)之前執行一些清理操作。如果我使用os.kill(p.pid, signal.SIGTERM)(不是SIGINT)手動終止處理程序中的子進程,那麼在通常會發生zombify的情況下,我可以成功地終止子進程。然而,一旦Ant開始產生輸出,當你點擊Ctrl + C時,你會從子進程中獲得一個堆棧跟蹤,因爲它已經殺死了子進程而無法殺死子進程本身。


編輯:觸發錯誤時

p = Popen('ls') 
def handle_sig_int(signum, stack_frame): 
    # perform cleanup 
    os.kill(p.pid, signal.SIGTERM) 
    exit(0) 
signal.signal(signal.SIGINT, handle_sig_int) 

p.wait() 

這將產生以下堆棧跟蹤:

File "****.py", line ***, in run_test 
    p.wait() 
File "/usr/lib/python2.5/subprocess.py", line 1122, in wait 
    pid, sts = os.waitpid(self.pid, 0) 
File "****.py", line ***, in handle_sig_int 
    os.kill(p.pid, signal.SIGTERM) 

我通過捕捉所提出的OSERROR固定它我的代碼看起來是這樣p.wait and exiting:

try: 
    p.wait() 
except OSError: 
    exit('The operation was interrupted by the user') 

這似乎在絕大多數我的測試運行。我偶爾會得到一個uname: write error: Broken pipe,但我不知道是什麼原因造成的。如果我在子進程開始顯示輸出之前按Ctrl + C的時間,似乎會發生這種情況。

回答

2

呼叫p.terminate()在SIGTERM處理程序:

if p.poll() is None: # Child still around? 
    p.terminate() # kill it 

[編輯]既然你堅持使用Python 2.5,使用os.kill(p.pid, signal.SIGTERM)代替p.terminate()。檢查應確保你沒有發現異常(或減少你得到的次數)。

爲了讓它更好,您可以捕獲異常並檢查消息。如果它的意思是「未找到子進程」,則忽略該異常。否則,用raise(無參數)重新拋出它。

+0

這就是我在第一次嘗試之前,我意識到p.terminate()是在Python 2.6中添加的,而我被困在2.5。不幸的是,我無法升級Python。 –

+0

我終於設法通過嘗試圍繞對p.wait()的調用並在發生OSError時發生錯誤而退出。 –