簡體   English   中英

Python模塊“readline”無法處理輸出重定向

[英]Python module “readline” can't handle output redirection

我導入了readline,為我的程序添加了自定義選項卡。 現在我需要保存程序的輸出,但任何重定向stdout的嘗試都會破壞選項卡完成功能。

我試過python3 script.py | tee txt.txt python3 script.py | tee txt.txt女巫似乎最接近打印到stdout和文本文件,但它不起作用。

這是自定義選項卡完成類,帶有來自main的函數調用(以防萬一):

import readline

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

def readlineset(a): # function called from main to turn on tab completion
                    # a is list of strings
    readline.set_completer(MyCompleter(a).complete)
    readline.parse_and_bind('tab: complete')

這是一個可能的解決方案:“猴子補丁” sys.stdout.write方法,以便寫入stdout任何內容也會被發送到文件。 我承認這不是很優雅,但它確實有效。 ;)

我已將Logger類設置為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')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM