【问题标题】:Printing to STDOUT and log file while removing ANSI color codes打印到 STDOUT 和日志文件,同时删除 ANSI 颜色代码
【发布时间】:2011-02-23 00:47:03
【问题描述】:

我有以下功能可以为我的屏幕消息着色:

def error(string):
    return '\033[31;1m' + string + '\033[0m'

def standout(string):
    return '\033[34;1m' + string + '\033[0m'

我使用它们如下:

print error('There was a problem with the program')
print "This is normal " + standout("and this stands out")

我想将输出记录到一个没有 ANSI 颜色代码的文件(除了 STDOUT),希望不必在每个 print 语句中添加第二个“记录”行。

原因是,如果您只是 python program.py > out,那么文件 out 将具有 ANSI 颜色代码,如果您在纯文本编辑器中打开,这看起来很糟糕。

有什么建议吗?

【问题讨论】:

    标签: python logging stdout ansi-colors


    【解决方案1】:

    sys.stdout.isatty 函数可能会有所帮助:

    from sys import stdout
    
    def error(string, is_tty=stdout.isatty()):
        return ('\033[31;1m' + string + '\033[0m') if is_tty else string
    
    def standout(string, is_tty=stdout.isatty()):
        return ('\033[34;1m' + string + '\033[0m') if is_tty else string
    

    这实际上是我能想到的使用未设置为 None 的默认参数的少数用途之一,因为默认参数是在 Python 中在编译时评估的,而不是像在 C++ 中那样在运行时评估...

    如果您确实需要,也可以显式地覆盖该行为,但这不会让您在重定向时操纵 stdout 本身。你有什么理由不使用logging 模块(也许你不知道)?

    【讨论】:

    • 优秀的答案 - 这可能正是我需要的。我实际上正在使用日志记录模块,但希望让用户可以选择重定向输出并获取人类可读的文件。日志本身是由日志模块创建的(通过你的方法,我很可能会得到我想要的)。
    • 我刚刚测试了你的方法,它完全符合预期。非常感谢!
    【解决方案2】:

    如果您希望同时打印到终端和日志文件,那么我建议使用日志记录模块。你甚至可以定义一个自定义格式化程序,这样记录到文件可以清除终端代码:

    import optparse
    import logging
    
    def error(string):
        return '\033[31;1m' + string + '\033[0m'
    
    def standout(string):
        return '\033[34;1m' + string + '\033[0m'
    
    def plain(string):
        return string.replace('\033[34;1m','').replace('\033[31;1m','').replace('\033[0m','')
    
    if __name__=='__main__':
        logging.basicConfig(level=logging.DEBUG,
                            format='%(message)s',
                            filemode='w')
        logger=logging.getLogger(__name__)    
        def parse_options():    
            usage = 'usage: %prog [Options]'
            parser = optparse.OptionParser()
            parser.add_option('-l', '--logfile', dest='logfile', 
                              help='use log file')
            opt,args = parser.parse_args()
            return opt,args
        opt,args=parse_options()
        if opt.logfile:
            class MyFormatter(logging.Formatter):
                def format(self,record):
                    return plain(record.msg)
            fh = logging.FileHandler(opt.logfile)
            fh.setLevel(logging.INFO)
            formatter = MyFormatter('%(message)s')
            fh.setFormatter(formatter)
            logging.getLogger('').addHandler(fh)
    
        logger.info(error('There was a problem with the program'))
        logger.info("This is normal " + standout("and this stands out"))
    

    test.py 仅打印到终端。

    test.py -l test.out 打印到终端和文件test.out

    在所有情况下,终端的文本都有颜色代码,而日志记录没有。

    【讨论】:

      【解决方案3】:

      unubtu 下面的回答很棒,但我认为 MyFormatter 需要稍作修改才能在 format() 方法中强制格式化

      class MyFormatter(logging.Formatter):
              def format(self,record):
                  msg = super(MyFormatter, self).format(record)
                  return plain(msg)
      

      【讨论】:

        猜你喜欢
        • 2018-01-07
        • 2013-10-18
        • 2015-01-10
        • 2021-12-04
        • 2018-02-13
        • 2016-07-21
        • 1970-01-01
        • 2020-03-17
        相关资源
        最近更新 更多