2010-10-11 55 views
5

我很難從python子進程模塊中獲得我想要的東西(應該是統一/平臺無關的抽象,afaik,但不要讓我開始吧:))。python subprocess with shell = True:重定向和平臺無關的子進程查殺

所以我簡單的事情是以下。我想

  • 啓動外部(標準輸入輸出)應用程序(可能具有子過程),其中,我使用殼式重定向(如「./myapp> stdout_log> stderr_log」)
    • 基本上我想執行shell命令行,所以我必須指定殼=真爲subprocess.Popen()(或者在命令行重定向將不會工作)
  • 我想發動這個命令行以異步的方式(所以它作爲一個獨立的子進程運行,但我的python proc ess不會等待它完成)
  • (我的父級python進程會不時地查看子進程的日誌以提取信息,但這與問題無關)
  • 如果我的父級python進程決定,它應該能夠終止這個子進程。

現在,我的主要問題是

  • 我基本上被迫使用殼=真,得到重定向工作
  • 父蟒蛇處理孩子的標準輸出/標準錯誤進程不是一個選項,因爲我找不到以非等待方式執行的功能(並且父級python進程必須在孩子運行時做其他事情)
  • 如果我使用殼=真然後subprocess.kill()將只終止
  • 我需要的是在任何平臺上工作的可靠的子進程的終止方法(但至少Linux和Windows)
殼而不是子進程

我希望我足夠具體。感謝提前任何提示/提示 - 我只是花了一整天的子過程,恕我直言它是 痛苦 遠離平臺無關或簡單:(但也許它只是我)

更新(2010年-10-13):

如果啓動一個子進程(即使外殼= FALSE),那麼subprocess.Popen.kill()函數將只殺死子進程(所以,如果有任何「孫子「流程,他們不會被終止)

我讀到有關使用preexec_fn參數設置所有的子進程的SID,但它僅限Unix:timeout a subprocess

+0

相關:[如何終止與shell = True啓動的python子進程](http://stackoverflow.com/q/4789837/95735) – 2012-10-18 23:11:15

回答

4

上次我遇到類似的情況時,我發現最簡單的(實際上唯一的)解決方案是啓動一個線程來處理您的子進程。你可以用這種方法採用不同的路線,分析shell風格的命令的管道,並在python代碼中執行這些命令(你說因阻塞而不是選項),這將同時修復殺死問題。基本上,線程封裝似乎是要走的路。

令人遺憾的是我的經驗與subprocess都在Windows平臺上,它有很多自己的小怪癖。 subprocess看起來有很多缺陷,儘管考慮到它應該替代的popen,popen2等模塊的存在,它必須做好工作。

+0

是的,我可能走線程的方式,因爲我不覺得像在這條路上浪費更多時間......感謝提示。如果這是任何安慰,linux上的子進程也有它自己的怪癖。 :( – riviera 2010-10-12 08:34:12

2

通過你的問題,一次一個狀況:

我基本上被迫使用shell =真,得到重定向工作

你不能只使用stdoutstderr參數?

out_log = open("stdout_log", "w") 
err_log = open("stderr_log", "w") 
subproc = subprocess.popen(..., stdout=out_log, stderr=err_log, ...) 

處理孩子的標準輸出/標準錯誤在父Python進程是不是一種選擇,因爲我無法在非等待的方式做它找到的功能(與父蟒蛇過程中必須做其他而孩子正在運行的東西)

這是因爲Windows。在Unix類型的操作系統上,您只需使用select模塊。 Windows只能在套接字上使用select,而不是文件。

如果我使用shell =真然後subprocess.kill()將只終止外殼,但不是孩子的過程

因爲當shell=True子進程,並命令它的孩子。

我需要在任何平臺上工作(但至少Linux和Windows)

是否可靠的子進程的終止方法甚至還存在一個用於Windows的可靠的子進程的終止方法?最後我聽說,即使任務管理器的結束任務也不是100%可靠的。而在Linux中,您可能無法殺死一個通過崩潰的驅動程序打開文件的進程。

就像斯蒂格瑪說的,對於Windows支持,您需要使用線程作爲子進程代理。此外,您應該嘗試使用shell=False運行,如果不能,請詳細說明爲什麼不。

+0

「因爲then shell = True shell是子進程,而命令是它的子進程。」 - 這是正確的,我意識到這一點,但我期望process _hierarchy_ termination(或至少一個選項如果子進程應該是一個'高級',獨立於平臺的模塊,恕我直言,這將是預期的行爲。 – riviera 2010-10-12 08:35:26

3

回答一些問題:

3

我也曾經有過類似的情況在最近,我創建了一個使用shell=True,後來又殺死它需要一個Python子。然而,由於shell參數,「真實」過程是shell的子進程,即主進程的孫子。殺死兒童外殼不會自動殺死孫子。

在我的頂級python腳本:

childProcess = subprocess.Popen('python other.py', shell=True) 

殺殼和「真正的工作」孫子,我這樣做:

subprocess.call("ps -ef | awk '$3 == \"" + str(childProcess.pid) + "\" {print $2}' | xargs kill -9", shell=True) 
childProcess.kill() 

第一行會殺死所有兒童子進程(根據ps -ef親子關係,第二行殺死孩子

有趣的是,在Ubuntu上這是必需的,但在Mac OSX上並不是必須的,因爲o在Mac上,孫子似乎接管了原來的子shell進程ID。