Python模块";readline";can';不处理输出重定向

Python模块";readline";can';不处理输出重定向,python,bash,Python,Bash,我导入了readline以将自定义选项卡完成添加到我的程序中。现在我需要保存程序的输出,但是任何重定向stdout的尝试都会破坏tab完成功能 我尝试了python3script.py | tee txt.txtwitch,它似乎最接近于打印标准输出和文本文件,但它不起作用 以下是自定义选项卡完成类,其中包含来自main的函数调用(以防万一): 这里有一个可能的解决方案:“monkey patch”是sys.stdout.write方法,这样写入stdout的任何内容都会被发送到文件中。我承认这

我导入了readline以将自定义选项卡完成添加到我的程序中。现在我需要保存程序的输出,但是任何重定向stdout的尝试都会破坏tab完成功能

我尝试了
python3script.py | tee txt.txt
witch,它似乎最接近于打印标准输出和文本文件,但它不起作用

以下是自定义选项卡完成类,其中包含来自main的函数调用(以防万一):


这里有一个可能的解决方案:“monkey patch”是
sys.stdout.write
方法,这样写入
stdout
的任何内容都会被发送到文件中。我承认这并不十分优雅,但它确实有效

我制作了
记录器
a类,这样就可以在
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
如果您不想将
一起使用,可以像这样使用
记录器

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')

这里有一个可能的解决方案:“monkey patch”是
sys.stdout.write
方法,这样写入
stdout
的任何内容都会被发送到文件中。我承认这并不十分优雅,但它确实有效

我制作了
记录器
a类,这样就可以在
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
如果您不想将
一起使用,可以像这样使用
记录器

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')

. 背景:readline设计用于交互式终端,但将输出重定向到其他地方(即使它将其回显给您,如
tee
),会使终端对readline显示为非交互式。如果您想记录交互式会话的输出,您可能更喜欢使用
typescript
(而不是
tee
)?。背景:readline设计用于交互式终端,但会将输出重定向到其他地方(即使它会将其回显给您,如
tee
),使终端对readline显示为非交互式。如果要记录交互式会话的输出(而不是
tee
),您可能更喜欢使用
typescript
)?