2011-05-25 79 views
1

我成功設法管到沒有進一步的管道,這樣一個命令的變量:如何在python中通過兩個管道連接管道變量的內容?

from subprocess import Popen, PIPE 

def exec_command(command, some_input): 
    proc = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE) 
    (stdout, stderr) = proc.communicate(input=some_input) 

...但試圖管它時,進一步的管道命令(例如管道,以焦油,然後進一步管道分裂),它似乎並沒有工作:

from subprocess import Popen, PIPE 

def exec_piped_command(command1, command2, some_input): 
    proc1 = Popen(command1, stdout=PIPE, stdin=PIPE) 
    proc2 = Popen(command1, stdin=proc1.stdout, stdout=PIPE) 
    (stdout, stderr) = proc2.communicate(input=some_input)[0] 

那麼,如何做正確的方法來做第二個變種?看起來上面代碼的問題是,「proc2.communicate()」命令中的輸入沒有到達proc1的stdin管道? (不知道雖然......不幸的是我對子進程語法有點困惑......)。

+0

proc2.communicate試圖一些輸入饋入管道,但對於PROC2輸入PIPE已經設置有從PROC1輸出PIPE --- UNIX管道不適合於多個寫入器/讀取過程(它們不是這樣隊列對象;也不像套接字)。這可能會導致您的代碼出現死鎖。 – 2011-05-25 08:41:59

+0

是的,真的,所以我的問題是,如何將變量提供給proc1的輸入,並仍然執行整個鏈接的命令? ...做proc1.communicate(輸入= some_input)也不工作... – 2011-05-25 08:43:27

+1

文體問題; '從x導入*'是非常糟糕的,並且讓所有**時間都氣餒。 – 2011-05-25 08:53:01

回答

1

一種可能性是將整個命令成立由shell執行(shell=TruePopen()通話的關鍵字ARGS中......只有用整個管道的兩端.communicate()(你輸入打算到Command的標準輸入,和你的標準輸出/標準錯誤的命令2的標準輸出/標準錯誤推出)。

一個更復雜的,但細粒,方法是使用沿着os.fork()os.pipe()os.dup2()可能還有一些os.fcntl()呼叫建立自己的子過程,用你自己定製的豐富功能,以及你需要的文件描述符所需的任何阻塞/非阻塞特性,然後,最後,你在每個這些中唱你自己的os.exec*函數。

顯然,後一種方法將複製已存在於subprocess模塊中的相當多的代碼。但是,它提供了以不通過subprocess.Popen類公開的方式以不同方式執行某些步驟的選項。

中間道路將是使一個子類,從subprocess.Popen

繼承當然可以優選通過Python代碼和模塊(如焦油,gzip來執行一些該流水線的部分,和拆分操作)。

+0

謝謝,我用shell = True尋求簡單的解決方案。不幸的是,不太安全,但我希望沒有向命令添加任何用戶可控制的字符串時,它會好起來的。 – 2011-05-26 09:40:06