如何记录Python交互式shell会话中发生的所有事情?

时间:2011-11-08 16:38:02

标签: python logging python-3.x

我希望能够实时访问解释器输入和错误以及标准输出。优选地,该信息将被写入文件,以便在输入每个解释器命令之后我可以轮询文件以进行更改。例如,给定一个解释器会话:

>>> 5 * 7
35
>>> print("Hello, world!")
Hello, world!
>>> "Hello, world!"
'Hello, world!'

我想在日志文件中看到以下内容:

> 5 * 7
35
> print("Hello, world!")
Hello, world!
> "Hello, world!"
'Hello, world!'

格式化并不重要;重要的是我可以在文件中搜索关键词以在会话期间触发交互式事件。

到目前为止我学到了什么:

Python的code模块允许我创建一个InteractiveConsole对象,我可以重新定义raw_input方法来登录文件,如下所示:

import code
class LoggedConsole(code.InteractiveConsole):
  def __init__(self, locals):
    super(LoggedConsole, self).__init__(locals)
    self.file = open('consolelog.dat', 'a')

  def __del__(self):
    self.file.close()

  def raw_input(self, prompt=""):
    data = input(prompt)
    self.file.write(data+'\n')
    return data

此外,InteractiveConsole使用内置的write方法记录错误,我可以将其重新定义为:

def write(self, data):
  sys.stderr.write(data)
  self.file.write(data+'\n')

我还了解到以下代码段将记录所有stdout:

class Tee(object):
  def __init__(self):
    self.file = open('consolelog.dat', 'a')
    self.stdout = sys.stdout

  def __del__(self):
    sys.stdout = self.stdout
    self.file.close()

  def write(self, data):
    self.file.write(data)
    self.stdout.write(data)

sys.stdout = Tee()

我(破碎)尝试将所有这些组合在一起就是创建一个LoggedConsole对象,并将其Tee传递给当地人。

console = LoggedConsole(locals={sys.stdout:LoggedExec()})
console.interact()

(之前我没有通过当地人,所以也许我在这里做错了,但我没有收到错误。)

无论如何,这将打开一个新的交互式控制台,并将记录(关闭后)所有输入和错误,但不会输出。我一直在撞击这个问题一段时间,我觉得我很接近,但也许不是..

此外,还有一种方法可以在会话期间发生所有这些吗?目前,所有日志记录都会在会话结束后进行。

感谢您的时间,对不起文字之墙。

编辑: 我希望能够在标准的Python解释器中实现这一目的,以实现可移植性。

EDIT2: Jaime的片段非常适合记录我需要的所有内容。但是,无论如何,我可以让它实时完成,而不是等待会话结束?

EDIT3: 想出来:)。最后的工作片段:

import code
import sys

class Tee(object):
  def __init__(self, log_fname, mode='a'):
    self.log = open(log_fname, mode)

  def __del__(self):
    # Restore sin, so, se
    sys.stdout = sys.__stdout__
    sys.stdir = sys.__stdin__
    sys.stderr = sys.__stderr__
    self.log.close()

  def write(self, data):
    self.log.write(data)
    self.log.flush()
    sys.__stdout__.write(data)
    sys.__stdout__.flush()

  def readline(self):
    s = sys.__stdin__.readline()
    sys.__stdin__.flush()
    self.log.write(s)
    self.log.flush()
    return s

  def flush(foo):
    return

sys.stdout = sys.stderr = sys.stdin = Tee('consolelog.dat', 'w')

console = code.InteractiveConsole()
console.interact()

5 个答案:

答案 0 :(得分:8)

我只在python2.7中测试过这个。我没有3个方便。

import code
import sys

class Tee(object):

  def __init__(self, log_fname, mode='a'):
    self.log = open(log_fname, mode)

  def __del__(self):
    # Restore sin, so, se
    sys.stdout = sys.__stdout__
    sys.stdir = sys.__stdin__
    sys.stderr = sys.__stderr__
    self.log.close()

  def write(self, data):
    self.log.write(data)
    sys.__stdout__.write(data)

  def readline(self):
    s = sys.__stdin__.readline()
    self.log.write(s)
    return s

# Tie the ins and outs to Tee.
sys.stdout = sys.stderr = sys.stdin = Tee('consolelog.dat', 'w')

console = code.InteractiveConsole()
console.interact()

答案 1 :(得分:5)

看看IPython(我自己没用过)。以下是文档中可能特别感兴趣的部分:http://ipython.org/ipython-doc/dev/interactive/reference.html#session-logging-and-restoring

答案 2 :(得分:3)

Doug Hellmann先生this Virtualenv article,了解如何记录iPython会话:

  

如果您习惯以这种方式在交互式提示下工作,但想要在关闭会话后记录您的操作以供将来参考,则可以使用IPython的日志记录功能将会话写入文件。要激活日志,请使用控制命令%logstart,如清单5所示。输出文件是Python源文件,因此很容易将其清理并在您使用时将其转换为“真实”模块完成了实验。

In [6]: %logstart
Activating auto-logging. Current session state plus future input saved.
Filename       : ipython_log.py
Mode           : rotate
Output logging : False
Raw input log  : False
Timestamping   : False
State          : active

In [7]: a = 5

In [8]: b = 6

In [9]: c = a * b

In [10]: c

Out[10]: 30

In [11]: d = [ a, b, c]

In [12]: d

Out[12]: [5, 6, 30]

In [13]: %logstop

答案 3 :(得分:2)

您只需使用unix脚本命令,请尝试:

script -a filename.txt
python
>> print("hi")
hi
>> exit()
exit

filename.txt将记录您在该会话中所做的一切,它将如下所示:

Script started on Sat Dec 14 11:18:41 2013
python
>> print('hi')
hi
>> exit()
exit

Script done on Sat Dec 14 11:18:59 2013

答案 4 :(得分:0)

您可以尝试使用我的日志工具。它还不完美,但它解决了我的问题,这似乎与你的问题类似。

https://github.com/hholst80/loginteractive

它的工作原理是使用LD_PRELOAD将stdin.txt(或$ STDIN)传递给stdout。它适用于python和octave,虽然我还没有测试那个