8
  1. 是否可以从 Python 脚本中捕获 Python 解释器的输出?
  2. 是否可以从 Python 脚本中捕获 Windows CMD 的输出?

如果是这样,我应该查看哪个图书馆(y|ies)?

4

5 回答 5

9

如果您正在谈论作为脚本“父级”的 python 解释器或 CMD.exe,那么不,这是不可能的。在每个类似 POSIX 的系统中(现在您似乎正在运行 Windows,这可能有一些我不知道的怪癖,YMMV)每个进程都有三个流,标准输入、标准输出和标准错误。Bu 默认(在控制台中运行时)这些被定向到控制台,但可以使用管道符号进行重定向:

python script_a.py | python script_b.py

这将脚本 a 的标准输出流与脚本 B 的标准输入流联系起来。在此示例中,标准错误仍会发送到控制台。请参阅Wikipedia上有关标准流的文章。

如果您正在谈论一个子进程,您可以像这样从 python 启动它(如果您想要双向通信,stdin 也是一个选项):

import subprocess
# Of course you can open things other than python here :)
process = subprocess.Popen(["python", "main.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x = process.stderr.readline()
y = process.stdout.readline()
process.wait()

有关管理流程的信息,请参阅 Python子流程模块。对于通信,process.stdin 和 process.stdout 管道被视为标准文件对象

对于管道使用,从标准输入读取lassevk建议您执行以下操作:

import sys
x = sys.stderr.readline()
y = sys.stdin.readline()

sys.stdin 和 sys.stdout 是如上所述的标准文件对象,在sys模块中定义。您可能还想看看管道模块。

在我的示例中使用 readline() 读取数据是一种非常幼稚的获取数据的方式。如果输出不是面向行的或不确定的,您可能想研究轮询,不幸的是它在 Windows 中不起作用,但我确信那里有一些替代方案。

于 2008-08-24T09:39:08.247 回答
5

我想我可以为你的问题的第一部分指出一个很好的答案。

1. 是否可以从 Python 脚本中捕获 Python 解释器的输出?

答案是“”,我个人喜欢从PEP 343 中的示例中提取的以下内容——“with”声明文档。

from contextlib import contextmanager
import sys

@contextmanager
def stdout_redirected(new_stdout):
    saved_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout.close()
        sys.stdout = saved_stdout

并像这样使用:

with stdout_redirected(open("filename.txt", "w")):
    print "Hello world"

它的一个很好的方面是它可以选择性地应用于脚本执行的一部分,而不是整个范围,并且即使在其上下文中引发未处理的异常时也保持有效。如果您在第一次使用后以附加模式重新打开文件,您可以将结果累积到一个文件中:

with stdout_redirected(open("filename.txt", "w")):
    print "Hello world"

print "screen only output again"

with stdout_redirected(open("filename.txt", "a")):
    print "Hello world2"

当然,上述内容也可以扩展到重定向sys.stderr到相同或另一个文件。另请参阅相关问题的答案。

于 2010-07-31T16:40:30.793 回答
3

事实上,你绝对可以,而且它是美丽的,丑陋的,同时也是疯狂的!

您可以将 sys.stdout 和 sys.stderr 替换为收集输出的 StringIO 对象。

这是一个示例,将其保存为 evil.py:

import sys
import StringIO

s = StringIO.StringIO()

sys.stdout = s

print "hey, this isn't going to stdout at all!"
print "where is it ?"

sys.stderr.write('It actually went to a StringIO object, I will show you now:\n')
sys.stderr.write(s.getvalue())

当你运行这个程序时,你会看到:

  • 没有任何东西进入标准输出(通常打印到的地方)
  • 写入 stderr 的第一个字符串是以 'It' 开头的字符串
  • 接下来的两行是在 StringIO 对象中收集的

像这样替换 sys.stdout/err 是所谓的猴子补丁的应用程序。无论是否“支持”,意见可能会有所不同,这绝对是一个丑陋的黑客,但它在尝试包裹外部东西一两次时拯救了我的培根。

在 Linux 上测试,而不是在 Windows 上测试,但它应该也能正常工作。让我知道它是否适用于 Windows!

于 2008-08-26T23:16:16.610 回答
1

你想要subprocess。具体看17.1.1中的Popen,17.1.2中的通信。

于 2008-08-24T09:27:54.140 回答
0

你是在什么情况下问的?

您是否尝试从在命令行启动的程序中捕获输出?

如果是这样,那么这是如何执行它:

somescript.py | your-capture-program-here

并读取输出,只需从标准输入读取。

另一方面,如果您正在程序中执行该脚本或 cmd.exe 或类似文件,并且想要等到脚本/程序完成并捕获其所有输出,那么您需要查看库您用来启动该外部程序的调用,很可能有一种方法可以要求它为您提供一些方法来读取输出并等待完成。

于 2008-08-24T09:05:20.947 回答