【问题标题】:Python, logging print statements while having them print to stdoutPython,记录打印语句,同时将它们打印到标准输出
【发布时间】:2013-07-25 20:38:20
【问题描述】:

我有一个经常使用打印语句的长 python 脚本,我想知道是否可以添加一些代码,将所有打印语句记录到文本文件或类似文件中。当用户在整个程序中得到提示时,我仍然希望所有打印语句都进入命令行。如果可能的话,记录用户的输入也是有益的。

我发现这在一定程度上回答了我的问题,但它使得“打印”语句不再打印到命令行

Redirect Python 'print' output to Logger

【问题讨论】:

  • @Robᵩ ha ha ha
  • @Stephan - 我觉得我不好笑。我试图了解 OP 真正想要我们做什么。
  • @Robᵩ 我想他是在问如何让print "hi" 用 1 个语句去两个不同的地方

标签: python logging printing stdout


【解决方案1】:

您可以将其添加到您的脚本中:

import sys
sys.stdout = open('logfile', 'w')

这将使打印语句写入logfile

如果你想要打印到stdout 和文件的选项,你可以试试这个:

class Tee(object):
    def __init__(self, *files):
        self.files = files
    def write(self, obj):
        for f in self.files:
            f.write(obj)

f = open('logfile', 'w')
backup = sys.stdout
sys.stdout = Tee(sys.stdout, f)

print "hello world"  # this should appear in stdout and in file

要恢复到仅打印到控制台,只需恢复“备份”

sys.stdout = backup

【讨论】:

    【解决方案2】:

    这是一个执行您描述的程序:

    #! /usr/bin/python3
    
    class Tee:
        def write(self, *args, **kwargs):
            self.out1.write(*args, **kwargs)
            self.out2.write(*args, **kwargs)
        def __init__(self, out1, out2):
            self.out1 = out1
            self.out2 = out2
    
    import sys
    sys.stdout = Tee(open("/tmp/log.txt", "w"), sys.stdout)
    
    print("hello")
    

    【讨论】:

    • 为什么你们都使用一个类,为什么他们都叫Tee
    • 我使用了一个类,因为print 最终会调用sys.stdout.write()。因为我要替换sys.stdout,所以我的替换需要有一个.write()。我在unix tee program 之后将其命名为Tee,它本身就是以plumbing fixture of the same name 命名的。
    • 有趣。您是否还独立运行了我的程序,没有任何代码?那么它是否产生了一个非空的/tmp/log.txt
    • @reddman - 您可以尝试将self.out1.flush()self.out2.flush() 添加到Tee.write():
    【解决方案3】:

    如果您使用内置的logging module,您可以根据需要为您的记录器配置尽可能多的输出:到文件、到数据库、到电子邮件等。但是听起来您将打印混合用于两种不同的用途:记录(记录程序流程以供以后检查)和提示。真正的工作是将“打印”的这两种用途拆分为不同的功能,以便您在每个地方都能获得所需的东西。

    很多人replace python's generic sys.stdout and sys.stderr 自动对发送到控制台的文本进行处理。真正的控制台输出总是存在于sys.__stdout__sys.__stderr__ 中(所以你不必担心以某种方式“丢失”它)但是如果你将任何具有与文件相同的方法的对象粘贴到变量sys.stdoutsys.stderr你可以对输出过程做任何你喜欢的事情。

    【讨论】:

      【解决方案4】:

      hm...很难实现你自己的 print() 函数和装饰器来记录传递给你的 print 函数的任何内容吗?

      def logger(func):
          def inner(*args, **kwargs):
              log(*args, **kwargs)  # your logging logic
              return func(*args, **kwargs)
          return inner
      
      @logger
      def lprint(string_to_print):
          print(string_to_print)   
      

      【讨论】:

        【解决方案5】:

        在尝试在 python 3.7 上接受的最佳答案时,我遇到了以下异常:

            Exception ignored in: <__main__.Logger object at 0x7f04083760f0>
            AttributeError: 'Logger' object has no attribute 'flush'
        

        我添加了以下功能使其工作:

            def flush(self):
                pass
        

        【讨论】:

          猜你喜欢
          • 2013-05-01
          • 1970-01-01
          • 2020-07-29
          • 2012-09-25
          • 1970-01-01
          • 1970-01-01
          • 2012-04-14
          • 2017-09-08
          相关资源
          最近更新 更多