如何从 Python 脚本捕获 Python 解释器和/或 CMD.EXE 的输出?
题
- 是否可以从 Python 脚本捕获 Python 解释器的输出?
- 是否可以从 Python 脚本捕获 Windows CMD 的输出?
如果是这样,我应该查看哪个库?
解决方案
如果您正在谈论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中不起作用,但我确信那里有一些替代方案。
其他提示
我想我可以为你问题的第一部分指出一个好的答案。
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
重定向到相同或另一个文件。另请参阅回答相关问题。
事实上,你绝对可以,而且它既美丽,又丑陋,又疯狂!
您可以将 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 是所谓的 Monkeypatching 的应用。无论这是否“受支持”,意见可能会有所不同,这绝对是一个丑陋的黑客,但当我尝试包装外部东西一两次时,它拯救了我的培根。
在 Linux 上测试过,没有在 Windows 上测试过,但它应该也能正常工作。让我知道它是否适用于 Windows!
您需要子流程。请特别注意17.1.1中的Popen,并在17.1.2中进行沟通。
你在问哪个环境?
您是否尝试捕获从命令行启动的程序的输出?
如果是的话,那就是如何执行它:
somescript.py | your-capture-program-here
并读取输出,只需从标准输入读取。
另一方面,如果您正在程序中执行该脚本或cmd.exe或类似程序,并希望等到脚本/程序完成并捕获其所有输出,那么您需要查看在库中调用你用来启动那个外部程序,很可能有一种方法可以让它给你一些方法来读取输出并等待完成。