這裏是一個可能的解決方案:「猴子補丁」的sys.stdout.write
方法,以便任何寫入stdout
也得到發送到一個文件。我承認這不完全優雅,但它的工作原理。 ;)
我製作了Logger
class a Context Manager,以便它可以在with
語句中使用。
import readline
import sys
class MyCompleter(object):
def __init__(self, options):
self.options = sorted(options)
def complete(self, text, state):
if state == 0:
if text:
self.matches = [s for s in self.options if s and s.startswith(text)]
else:
self.matches = self.options[:]
try:
return self.matches[state]
except IndexError:
return None
class Logger(object):
''' Monkey-patch sys.stdout
to copy output to a file
'''
def __init__(self, fname):
self.fh = open(fname, 'w')
self.oldwrite = sys.stdout.write
sys.stdout.write = self.write
def write(self, s):
self.oldwrite(s)
self.fh.write(s)
def close(self):
self.fh.close()
sys.stdout.write = self.oldwrite
# Define Context Manager methods so Logger
# can be used in a `with` statement
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
return False
def readlineset(a):
''' Turn on tab completion.
`a` is list of strings that will be completed
'''
readline.set_completer(MyCompleter(a).complete)
readline.parse_and_bind('tab: complete')
def main():
readlineset(['python', 'stack', 'overflow', 'exchange'])
with Logger('mylog.txt'):
while True:
s = input('> ')
if s == 'quit':
break
print(repr(s), len(s))
print('bye')
if __name__ == '__main__':
main()
演示
> This is a test
'This is a test' 14
> python on stack overflow
'python on stack overflow' 24
> quit
bye
mylog.txt
'This is a test' 14
'python on stack overflow' 24
如果你不想使用with
,您可以使用Logger
這樣的:
def main():
readlineset(['python', 'stack', 'overflow', 'exchange'])
logger = Logger('mylog.txt')
while True:
s = input('> ')
if s == 'quit':
break
print(repr(s), len(s))
logger.close()
print('bye')
[可能相關的Python問題](https://bugs.python.org/issue24829)。背景:readline被設計用於在交互式終端上工作,但將輸出重定向到其他地方(即使它將它回顯給你,就像'tee'),使終端對readline看起來是非互動的。 –
如果你想記錄交互式會話的輸出(而不是'tee'),你可能更喜歡使用'typecript'? –