2014-10-31 47 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

相关问题