如何记录Python交互式环境中的所有操作?
我想要实时访问解释器的输入、错误信息和标准输出。最好是把这些信息写入一个文件,这样我就可以在每次输入解释器命令后检查文件的变化。例如,在一个解释器会话中:
>>> 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')
我还了解到,以下代码片段可以记录所有的标准输出:
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
传给它的 locals。
console = LoggedConsole(locals={sys.stdout:LoggedExec()})
console.interact()
(我之前没有传过 locals,所以可能这里做得不对,但我没有收到错误信息。)
总之,这将打开一个新的交互式控制台,并在关闭后记录所有输入和错误,但不记录输出。我在这方面纠结了很久,感觉快要成功了,但又不太确定。
另外,有没有办法让这一切在会话 进行中 就发生?目前所有的记录都是在会话结束后进行的。
谢谢你的时间,抱歉文字有点多。
编辑:我希望能在标准的Python解释器中实现这个功能,以便于移植。
编辑2:Jaime的代码片段非常有效,可以记录我需要的所有内容。不过,有没有办法让它实时记录,而不是等会话结束后再记录?
编辑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)
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()
4 个回答
你可以简单地使用unix的script命令,试试这个:
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
请查看Doug Hellmann的这篇关于Virtualenv的文章,里面介绍了如何记录一个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
我只在python2.7中测试过这个。手头没有python3。
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()