交互式Python脚本输出存储在某个文件中

时间:2009-12-20 20:47:27

标签: python logging

如何执行Python脚本以及从中调用的所有脚本执行的所有活动的日志记录?

我有几个Bash脚本,但现在编写了一个调用所有这些Bash脚本的Python脚本。我希望将这些脚本生成的所有输出存储在某个文件中。

脚本是交互式Python脚本,即包含raw_input行,所以我不能像'python script.py |那样。 tee log.txt'用于整体Python脚本,因为某些原因在屏幕上看不到问题。

以下是脚本的一段摘录,它调用了一个shell脚本。

    cmd = "somescript.sh"
    try:
    retvalue = subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError:
    print ("script command has been failed")
    sys.exit("exit from script")

您认为可以在这做什么?

修改

基于Alex答案的两个子问题:

  1. 如何对存储在输出文件中的问题做出答案?例如,在ok = raw_input(prompt)行,系统会询问用户是否有问题,我也希望记录答案。

  2. 我读到有关Popen的信息并且没有使用,因为它将数据缓冲在内存中。这里输出量很大,我也需要关注标准输出的标准误差。你知道这是否可以用Popen和沟通方法来处理?

3 个答案:

答案 0 :(得分:7)

让Python自己的print转到终端和文件并不难:

>>> import sys
>>> class tee(object):
...   def __init__(self, fn='/tmp/foo.txt'):
...     self.o = sys.stdout
...     self.f = open(fn, 'w')
...   def write(self, s):
...     self.o.write(s)
...     self.f.write(s)
... 
>>> sys.stdout = tee()
>>> print('hello world!')
hello world!
>>> 
$ cat /tmp/foo.txt
hello world!

这应该适用于Python 2和Python 3。

要类似地指导子命令的输出,请不要使用

retvalue = subprocess.check_call(cmd, shell=True)

允许cmd的输出转到常规的“标准输出”,而是自己抓取并重新发出它,如下所示:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
so, se = p.communicate()
print(so)
retvalue = p.returncode

假设您不关心标准错误(仅标准输出)并且cmd的输出量相当小(因为.communicate将数据缓存在内存中) - 这很容易如果任何一个假设不符合您的确切要求,就进行调整。

编辑:OP现在已经澄清了对此答案的长篇评论中的规范:

  • 如何在答案上做出答案 存储在输出文件中的问题 还有?例如,在线ok = raw_input(提示)用户将是 问我这个问题 喜欢记录的答案。

使用如下功能:

def echoed_input(prompt):
    response = raw_input(prompt)
    sys.stdout.f.write(response)
    return response

而不仅仅是应用程序代码中的raw_input(当然,这是专门为与上面显示的tee类合作而编写的。)

  • 我读到了关于Popen和沟通的消息 并且没有使用,因为它缓冲了 内存中的数据。这里的输出量 很大,我需要关心 标准输出的标准错误 同样。你知道吗? 可以处理Popen和 沟通方法也是如此?

communicate只要您获得更多输出(和标准错误)而不是舒适地适合内存,可以说是好的,比如根据类型的数量,最多几千兆字节你正在使用的机器。

如果符合此假设,只需将上述内容重新编码为:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
                     stderr=subprocess.STDOUT)
so, se = p.communicate()
print(so)
retvalue = p.returncode

即,只是重定向子命令的stderr以混入其stdout。

如果您不得不担心来自您的千兆字节(或其他),那么

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
                     stderr=subprocess.STDOUT)
for line in p.stdout:
  sys.stdout.write(p)
p.wait()
retvalue = p.returncode

(一次获取并发出一行)可能更可取(这取决于cmd不期望其标准输入的任何内容,当然......因为,如果它 期待什么,它不会得到它,问题开始变得具有挑战性; - )。

答案 1 :(得分:1)

Python有一个跟踪模块:trace。用法:python -m trace --trace file.py

答案 2 :(得分:1)

如果要捕获任何脚本的输出,那么在* nix-y系统上,您可以将stdout和stderr重定向到文件:

./script.py >> /tmp/outputs.txt 2>> /tmp/outputs.txt

如果你希望脚本完成所有,而不仅仅是它们打印的内容,那么python跟踪模块将不会跟踪你的python执行的外部脚本所做的事情。如果你足够幸运拥有一个支持它的系统,唯一可以跟踪程序完成每个操作的东西就像DTrace。 (OS X Instruments基于DTrace)