2014-10-31 46 views
0

如果可能我不想使用subProcess.popen。我想捕獲子進程啓動的stdout的原因是因爲我需要將子進程的輸出保存到一個變量中以便以後再顯示出來。不過,我還沒有找到一種方法來做到這一點。我還需要激活多個程序,而不必關閉活動的程序。我還需要控制父流程中的子流程。如何將打印和標準輸出重定向到管道並從父進程讀取它?

我推出一個子這樣

listProgram = ["./perroquet.py"] 
listOutput = ["","",""] 
tubePerroquet = os.pipe() 
pipeMain = os.pipe() 
pipeAge = os.pipe() 
pipeSavoir = os.pipe() 
pid = os.fork() 
process = 1 
if pid == 0: 
    os.close(pipePerroquet[1]) 
    os.dup2(pipePerroquet[0],0) 
    sys.stdout = os.fdopen(tubeMain[1], 'w') 
    os.execvp("./perroquet.py", listProgram) 

現在你可以看到我啓動程序與os.execvp和使用os.dup2()重定向孩子的標準輸出。但是我不確定我在代碼中做了什麼,並且想知道將os.dup2重定向stdout然後能夠在父進程中讀取它的正確方法。

謝謝你的幫助。

+0

那麼你有什麼不工作什麼變化?以什麼方式? – martineau 2014-10-31 15:50:48

+0

爲什麼你不能使用子進程? – Vyktor 2014-10-31 16:11:09

+0

由於程序的性質,我需要執行任何操作(包括命令),除非我誤解了'subProcess.popen'的工作方式,執行一個命令和一個程序需要不同的格式化 – IIIlII47IIIlII 2014-10-31 16:14:53

回答

0

我不明白爲什麼你不想使用優秀的子過程模塊,可以爲您節省大量的鍋爐板代碼(以及儘可能多的錯誤可能性......)。無論如何,我認爲perroquet.py是一個python腳本,而不是一個可執行程序。 Shell知道如何爲腳本找到正確的解釋器,但exec系列是低級函數,它需要一個可執行程序實際

你至少應該有這樣的事情:

listProgram = [ "python", "./perroquet.py","",""] 
... 
    os.execvp("python", listProgram) 

但我寧願使用:

prog = subprocess.Popen(("python", "./perroquet.py", "", ""), stdout = PIPE) 

,甚至因爲你已經在Python進口並直接從那裏調用的函數。

編輯:

看起來thart你真正想要的是:

  • 用戶給你的命令(幾乎可以是任何東西)
  • [您驗證該命令是安全] - 不確定如果你打算這樣做,但你應該...
  • 你讓shell執行命令並獲得它的輸出 - 你也可能想讀stderr並控制退出代碼

你應該嘗試像

while True: 
    cmd = raw_input("commande :") # input with Python 3 
    if cmd.strip().lower() == exit: break 
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
     stderr=subprocess.PIPE, shell=True) 
    out, err = proc.communicate() 
    code = proc.returncode 
    print("OUT", out, "ERR", err, "CODE", code) 

這是絕對不安全的,因爲這個代碼執行任何命令作爲底層殼會做(包括rm -rf *rd /s/q .,...),但它給你的輸出,命令的輸出和返回代碼,並且可以使用它是一個循環。唯一的限制是,當你爲每個命令使用一個不同的shell時,你不能使用改變shell環境的命令 - 它們將被執行但不會有效果。

+0

我不想使用'subProcess.Popen '因爲我需要執行任何操作,包括終端命令,我將從用戶那裏獲得所有這些,這意味着我無法調用子進程。但是,如果有一種方法可以調用'subProcess.popen'並使用列表或任何其他方式格式化字符串,我很想知道它。感謝您的幫助 – IIIlII47IIIlII 2014-10-31 16:20:35

+0

問題是,因爲我需要能夠在不關閉當前的程序的情況下繼續啓動程序,只需將輸出發送到所有已激活的程序就可以了? (我知道啓動多個程序的必要性不在我原來的問題中,我會立即糾正它) – IIIlII47IIIlII 2014-10-31 16:55:39

+0

我沒有想到你不能通過管道傳遞變量的事實,因此此解決方案不適用於我。感謝您抽出寶貴時間幫助我 – IIIlII47IIIlII 2014-11-03 17:11:57

0

這裏有一個解決方案,如果你需要提取環境

from subprocess import Popen, PIPE 
import os  

def execute_and_get_env(cmd, initial_env=None): 
    if initial_env is None: 
     initial_env = os.environ 

    r_fd, w_fd = os.pipe() 
    write_env = "; env >&{}".format(w_fd) 

    p = Popen(cmd + write_env, shell=True, env=initial_env, pass_fds=[w_fd], stdout=PIPE, stderr=PIPE) 
    output, error = p.communicate() 

    # this will cause problems if the environment gets very large as 
    # writing to the pipe will hang because it gets full and we only 
    # read from the pipe when the process is over 
    os.close(w_fd) 
    with open(r_fd) as f: 
     env = dict(line[:-1].split("=", 1) for line in f) 

    return output, error, env 

export_cmd = "export my_var='hello world'" 
echo_cmd = "echo $my_var" 

out, err, env = execute_and_get_env(export_cmd) 
out, err, env = execute_and_get_env(echo_cmd, env) 

print(out) 
+0

這是一個很好的答案,我想我有一個解決方案來清空管道。由於我將在孩子中啓動該過程,因此我會通過管道發送'p'變量,以便能夠不斷地從管道讀取 – IIIlII47IIIlII 2014-11-01 20:38:20

+0

@ IIIlII47IIIlII我不確定你的意思。但我很高興你能解決你的問題。 – Dunes 2014-11-01 21:22:45

相關問題