【问题标题】:Executing shell program in Python without printing to screen在 Python 中执行 shell 程序而不打印到屏幕上
【发布时间】:2013-08-13 16:10:04
【问题描述】:

有没有一种方法可以让我从 Python 执行一个 shell 程序,将其输出打印到屏幕上,并将其输出读入一个变量而不在屏幕上显示任何内容?

这听起来有点混乱,所以也许我可以通过一个例子更好地解释它。

假设我有一个程序在执行时会在屏幕上打印一些东西

bash> ./my_prog
bash> "Hello World"

当我想将输出读入 Python 中的变量时,我读到一个好方法是像这样使用 subprocess 模块:

my_var = subprocess.check_output("./my_prog", shell=True)

使用这个结构,我可以将程序的输出输入到my_var(这里是"Hello World"),但是当我运行 Python 脚本时它也会打印到屏幕上。有什么办法可以抑制这种情况吗?我在 subprocess 文档中找不到任何内容,所以也许还有另一个模块可以用于此目的?

编辑: 我刚刚发现commands.getoutput() 让我这样做。但是有没有办法在subprocess中实现类似的效果呢?因为我打算在某个时候制作 Python3 版本。


EDIT2:特定示例

python脚本摘录:

oechem_utils_path = "/soft/linux64/openeye/examples/oechem-utilities/"\
        "openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/"\
        "oechem-utilities/"

rmsd_path = oechem_utils_path + "rmsd"

for file in lMol2:
            sReturn = subprocess.check_output("{rmsd_exe} {rmsd_pars}"\
                 " -in {sIn} -ref {sRef}".format(rmsd_exe=sRmsdExe,\
                 rmsd_pars=sRmsdPars, sIn=file, sRef=sReference), shell=True)
    dRmsds[file] = sReturn

屏幕输出(注意不是“所有”都打印到屏幕上,只有一部分 输出,如果我使用 commands.getoutput 一切正常:

/soft/linux64/openeye/examples/oechem-utilities/openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/oechem-utilities/rmsd: mols in: 1  out: 0
/soft/linux64/openeye/examples/oechem-utilities/openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/oechem-utilities/rmsd: confs in: 1  out: 0
/soft/linux64/openeye/examples/oechem-utilities/openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/oechem-utilities/rmsd - RMSD utility [OEChem 1.7.2]

/soft/linux64/openeye/examples/oechem-utilities/openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/oechem-utilities/rmsd: mols in: 1  out: 0
/soft/linux64/openeye/examples/oechem-utilities/openeye/toolkits/1.7.2.4/redhat-RHEL5-g++4.3-x64/examples/oechem-utilities/rmsd: confs in: 1  out: 0

【问题讨论】:

  • 你确定吗?因为checkout_output 只是将输出作为字符串返回,所以屏幕上不会刷新任何内容。
  • 是的,我会在稍后将确切的内容发布到我的初始查询中并输出
  • 我在EDIT2下添加了特定问题

标签: python python-2.7 subprocess


【解决方案1】:

要添加到 Ryan Haining 的答案,您还可以处理 stderr 以确保没有任何内容打印到屏幕上:

 p = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, close_fds=True)
out,err = p.communicate()

【讨论】:

  • 啊,我忘了stderr!谢谢,这解决了我的问题!
  • 您可以使用output = check_output(cmd, stderr=STDOUT),在一个变量中同时捕获标准输出和标准错误。
【解决方案2】:

如果 subprocess.check_ouput 不适合您,请使用 Popen 对象和 PIPE 在 Python 中捕获程序的输出。

prog = subprocess.Popen('./myprog', shell=True, stdout=subprocess.PIPE)
output = prog.communicate()[0]

.communicate() 方法将等待程序完成执行,然后返回一个 (stdout, stderr) 的元组,这就是为什么您要使用 [0] 的原因。

如果您还想捕获stderr,则将stderr=subprocess.PIPE 添加到Popen 对象的创建中。

如果您希望在运行时捕获prog 的输出而不是等待它完成,您可以调用line = prog.stdout.readline() 一次读取一行。请注意,如果没有可用的线路直到有可用线路,这将挂起。

【讨论】:

  • 谢谢,我之前尝试过,它仍然将一些输出打印到屏幕上。嗯,也许这只是这个特定程序的问题,我会选择commands.getoutput
  • @SebastianRaschka 正如我在回答中所说,您还可以捕获stderr,这可能是打印“某些输出”的原因
  • 是的,谢谢,只是以某种方式忽略了它,因为此输出只是“常规”输出,而不是“错误”通知
【解决方案3】:

我一直用Subprocess.Popen,正常没有输出

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-28
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    相关资源
    最近更新 更多