【问题标题】:How to output to the console and file?如何输出到控制台和文件?
【发布时间】:2012-07-04 17:13:25
【问题描述】:

我正在尝试在 python 中找到一种方法来将脚本执行日志重定向到文件以及stdout 以pythonic 方式。有什么简单的方法可以实现吗?

【问题讨论】:

  • 嗯,到目前为止你得到了什么?
  • 在 linux 控制台上这是script | tee logfilename
  • 你的意思是这样的吗? [Python 输出缓冲][1] [1]:stackoverflow.com/questions/107705/python-output-buffering
  • 使用python日志库!!!它是我在 python 中最喜欢的库:D.

标签: python


【解决方案1】:

使用日志模块(http://docs.python.org/library/logging.html):

import logging

logger = logging.getLogger('scope.name')

file_log_handler = logging.FileHandler('logfile.log')
logger.addHandler(file_log_handler)

stderr_log_handler = logging.StreamHandler()
logger.addHandler(stderr_log_handler)

# nice output format
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_log_handler.setFormatter(formatter)
stderr_log_handler.setFormatter(formatter)

logger.info('Info message')
logger.error('Error message')

【讨论】:

    【解决方案2】:

    我想出了这个[未经测试]

    import sys
    
    class Tee(object):
        def __init__(self, *files):
            self.files = files
        def write(self, obj):
            for f in self.files:
                f.write(obj)
                f.flush() # If you want the output to be visible immediately
        def flush(self) :
            for f in self.files:
                f.flush()
    
    f = open('out.txt', 'w')
    original = sys.stdout
    sys.stdout = Tee(sys.stdout, f)
    print "test"  # This will go to stdout and the file out.txt
    
    #use the original
    sys.stdout = original
    print "This won't appear on file"  # Only on stdout
    f.close()
    

    python 中的print>>xyz 将期望xyz 中的write() 函数。您可以使用您自己的自定义对象。否则,您也可以让 sys.stdout 引用您的对象,在这种情况下,即使没有 >>xyz,它也会被 tee-ed。

    【讨论】:

    • 太棒了。这按我预期的方式工作..因为我是编程新手,所以试图理解一点.. 使用命令 Tee(sys.stdout,f) 时如何调用类 Tee,因为类 def 只涉及一个对象(可能是文件对象)?请指教
    • 如果你问write 是如何被调用的。print 操作最终会变成sys.stdout.write(..)。让sys.stdout 指向一个定义了.write(..) 的对象就可以了。
    • 我发现这对于编写快速的 LaTeX 生成器特别有用。 @Thrustmaster 我做了另一个小修改,发布了Gist。感谢您发布此信息!
    • 这很好用,除非使用子进程。在我的主函数中,我这样做了,然后在 main 之外调用一个函数,该函数调用子进程,并且子进程的输出不会写入文件(尽管它正常写入 stdout)
    • 您不能用sys.__stdout__ 恢复sys.stdout 而不是将其保存到变量中吗?
    【解决方案3】:

    我只想在 Serpens 答案的基础上添加以下内容:

    logger.setLevel('DEBUG')
    

    这将允许您选择要记录的消息级别。

    以 Serpens 为例,

    logger.info('Info message')
    

    不会被记录,因为它默认只记录警告及以上。

    更多关于使用的关卡可以阅读here

    【讨论】:

      【解决方案4】:

      可能是最短的解决方案:

      def printLog(*args, **kwargs):
          print(*args, **kwargs)
          with open('output.out','a') as file:
              print(*args, **kwargs, file=file)
      
      printLog('hello world')
      

      将“hello world”写入sys.stdoutoutput.out,其工作方式与 print() 完全相同。

      注意: 请不要为 printLog 函数指定文件参数。不支持printLog('test',file='output2.out') 之类的调用。

      【讨论】:

      • 是否有任何性能缺陷?我的意思是重复打开/关闭文件?
      • 取决于您的用例。如果您将printLog 放入一个经常重复的循环中,这将对性能产生很大影响。但是将print 设置为也不是一个好主意!一个想法可能是添加一些缓冲区,然后在日志文件中一次写入 100 行。这可能与您的记录器的想法相悖
      • 要指定文件名,只需将printLog与另一个采用文件名的函数包装起来:def print_log(msg, filename):,并在其中定义您的printLog(可以将其命名为_print_log以表示隐私),并且在print_log 内,致电_print_log(msg)。这样,您的内部函数也可以从外部 print_log 函数访问 filename 参数。所以它可以使用它来代替output.out
      【解决方案5】:

      您应该使用内置此功能的logging 库。您只需将处理程序添加到记录器以确定将输出发送到何处。

      【讨论】:

        【解决方案6】:

        最简单的解决方案是重定向标准输出。在您的 python 程序文件中使用以下内容:

        if __name__ == "__main__":
           sys.stdout = open('file.log', 'w')
           #sys.stdout = open('/dev/null', 'w')
           main()
        

        任何STD输出(例如print 'hi there'的输出)将被重定向到file.log或者如果取消注释的第二行,任何输出将只是被抑制。 P>

        【讨论】:

        • 该指示只输出到文件..我要显示两个日志文件并到控制台... 跨度>
        【解决方案7】:

        创建输出文件和自定义函数:

        outputFile = open('outputfile.log', 'w')
        
        def printing(text):
            print(text)
            if outputFile:
                outputFile.write(str(text))
        

        然后调用打印函数而不是代码中的 print(text)。

        printing("START")
        printing(datetime.datetime.now())
        printing("COMPLETE")
        printing(datetime.datetime.now())
        

        【讨论】:

          【解决方案8】:

          这是对@UltraInstinct 的 Tee 类的一个小改进,被修改为上下文管理器并且还捕获任何异常。

          import traceback
          import sys
          
          # Context manager that copies stdout and any exceptions to a log file
          class Tee(object):
              def __init__(self, filename):
                  self.file = open(filename, 'w')
                  self.stdout = sys.stdout
          
              def __enter__(self):
                  sys.stdout = self
          
              def __exit__(self, exc_type, exc_value, tb):
                  sys.stdout = self.stdout
                  if exc_type is not None:
                      self.file.write(traceback.format_exc())
                  self.file.close()
          
              def write(self, data):
                  self.file.write(data)
                  self.stdout.write(data)
          
              def flush(self):
                  self.file.flush()
                  self.stdout.flush()
          

          使用上下文管理器:

          print("Print")
          with Tee('test.txt'):
              print("Print+Write")
              raise Exception("Test")
          print("Print")
          

          【讨论】:

            猜你喜欢
            • 2021-06-05
            • 2018-12-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-03-18
            • 2020-02-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多