【问题标题】:Interactive Python script output stored in some file存储在某个文件中的交互式 Python 脚本输出
【发布时间】:2009-12-20 20:47:26
【问题描述】:

如何记录由 Python 脚本完成的所有活动以及从中调用的所有脚本?

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

脚本是交互式 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 和通信方法来处理?

【问题讨论】:

标签: python logging


【解决方案1】:

让 Python 自己的prints 去终端和文件并不难:

>>> 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(prompt) 用户将是 问了这个问题,我会 也喜欢记录的答案。

使用如下函数:

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 不期望从其标准输入中得到任何东西,当然......因为,如果它期待什么,它不会得到它,问题开始变得具有挑战性;-)。

【讨论】:

  • 你的类 tee() 有一些奇妙的扭曲。在了解 Python 之前,我显然花了太多年时间研究 C(和其他恐龙语言)。
  • 嗨,亚历克斯,感谢您的回答。根据您的回答,我有两个子问题。 1. 如何对输出文件中存储的问题进行回答?例如在线 ok = raw_input(prompt) 将询问用户问题,我也想记录答案。 2.我阅读了Popen并进行通信并且没有使用,因为它在内存中缓冲数据。这里的输出量很大,我也需要关心标准输出的标准错误。你知道这是否可以用 Popen 和通信方法来处理?
  • @yart,当然,您可以按照您的要求做(如果您将详细的规格放入原始问题中,而不是让我们都猜测!-),让我编辑答案(同时你应该编辑你的问题,而不是让这些绝对重要的细节挂在评论中!)。
  • 非常感谢亚历克斯。我刚开始使用stackoverflow,这只是我的第二个问题。我还编辑了我原来的问题,所以它现在包含所有细节。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 谢谢 Autopopulated,但我提到的脚本是交互式的,这意味着您不会通过此重定向看到屏幕上的问题。您可以在脚本中尝试使用 ok = raw_input(prompt)。
    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 2016-05-29
    • 2018-02-06
    • 2021-10-26
    • 2020-12-01
    • 2020-12-16
    • 2022-10-06
    • 1970-01-01
    相关资源
    最近更新 更多