【问题标题】:Calling external program through Python and passing the output to stdout通过 Python 调用外部程序并将输出传递给 stdout
【发布时间】:2013-01-10 09:45:11
【问题描述】:

如何调用用 bash 脚本编写的外部程序,使该脚本产生的输出在 sys.stdout 中可用,以便我可以通过 python 将输出记录到文件中。

例如。我现在通过以下 sn-p 调用它们

if os.name == 'nt':
    path = module_dir_run+'/run.bat'
else:
    path = module_dir_run+'/run.sh'
if os.path.isfile(path):
    if (splitargs.arg):
        try:
            call([path, splitargs.arg])
        except:
            pass
    else:
        try:
            call([path])
        except:
            pass
else:
    print "Not found : " + path

当我存储 sys.stdout = file(filename, "w") 的值时,它会存储 python 输出的任何内容,而不是脚本输出的内容。

注意:我试图运行的脚本是一个交互式脚本,所以在调用结束后,控制又回到了 python,我怎样才能得到终端中写的所有内容? 有什么建议吗?

【问题讨论】:

  • 是否必须将输出写入stdout?我建议将其写入文件然后读取文件。
  • 你需要包含call是什么。
  • @InbarRose: subprocess.call 大概。
  • @MartijnPieters 是的,但也许它是一个用某种参数或其他东西实现它的函数......
  • 它是必需的,因为如果有人调用像 run modulename > output.txt 这样的函数

标签: python bash python-2.7


【解决方案1】:

我总是使用 subprocess.Popen() 从 Python 脚本中运行另一个程序。示例:

import subprocess

print "Starting process..."
process = subprocess.Popen(["echo", "a"], shell=False)
process.wait()
print "Done"

您可以像这样将进程的输出重定向到另一个文件:

import subprocess

print "Starting process..."
with open("./out.log", "w") as f:
    process = subprocess.Popen(["echo", "a"], shell=False, stdout=f)
    process.wait()
print "Done"

也可以通过'stderr'参数重定向stderr。

当您将当前脚本中的 sys.stdout 重定向到写入您自己的文件时,您也可以这样做以在您的子进程中重定向它:

import subprocess
import sys

sys.stdout = open("./out.log", "w")
print "Starting process..."
sys.stdout.flush()
process = subprocess.Popen(["echo", "a"], shell=False, stdout=sys.stdout)
process.wait()
print "Done"

【讨论】:

  • 脚本有交互功能,用户必须交互的地方,也会被记录下来吗?如果我事先将标准输出传递给文件描述符,则用户无法与脚本交互!
  • 所以你想让你的子进程的输出在控制台上可见并写入日志文件?至于交互,当前标准输入是隐式传递的,用户将能够从键盘输入命令。
  • 是的,这就是我想要的!但我希望用户与脚本进行本地交互,当脚本结束时,变量或标准输出可以存储它在终端中写入的任何内容。
  • 它可以做到,但它可能有点麻烦,当新的东西出现时,你必须依靠你的子进程来立即刷新标准输出。您的 Python 脚本需要能够打印到控制台,因此如果您重定向 sys.stdout,您需要将原始脚本保存在某个变量中,以便将子进程的输出写入其中。然后,您需要将子进程的标准输出重定向到一个单独的文件,并在主进程中循环读取该文件,直到进程退出。这样你就可以对输出做任何你想做的事情。
  • 我没听懂,你能举个简单的例子吗?
【解决方案2】:

您可以将此类调用的输出写入变量,例如:

variable = subprocess.Popen(
    ['ls', 'mydir/'],  # note that the command is split on whitespace
    stdout=subprocess.PIPE).communicate()[0]

【讨论】:

  • 我尝试运行的脚本具有交互功能,用户必须输入他们的姓名等,这也会被记录下来吗?
  • @SunnyRockzzs 所以你想让它像script.py arg1 arg2 一样可调用吗?如果我理解正确,也许这个stack overflow question 会带你走得更远
  • 我认为他的意思是他试图运行的脚本从标准输入读取。请注意他对“交互式”一词的使用。所以需要将stdin重定向回运行python脚本的shell。
【解决方案3】:

正如 Martijn Pieters 所述,您必须为您的 call() 呼叫提供替代的 stdout

基本上有两种方式: * 要么提供一个已经打开的文件(因为你已经改变了你的sys.stdout,这可能会很好) * 使用stdout=subprocess.PIPE 并自己阅读和处理stdout。 (不是通过subprocess.call(),而是通过subprocess.Popen()返回的对象。)

请注意,从操作系统的角度来看,更改 sys.stdout 并不会真正更改您进程的标准输出,而是会命令您的程序将所有内容输出到一个不常见的文件描述符上。

【讨论】:

    【解决方案4】:

    这可能有用。特别是因为大多数其他答案不明白您需要将父 shell 的标准输入重定向到子进程的标准输入,因为您调用的程序/脚本是“交互式的”。

    Python and subprocess input piping

    【讨论】:

      猜你喜欢
      • 2017-01-19
      • 2011-08-01
      • 1970-01-01
      • 2011-11-28
      • 2014-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多