【问题标题】:redirect prints to log file将打印重定向到日志文件
【发布时间】:2011-01-31 14:12:31
【问题描述】:

好的。我已经完成了我的第一个 python 程序。它有大约 1000 行代码。 在开发过程中,我在使用 os.system() 运行命令之前放置了大量 print 语句 像这样说,

print "running command",cmd
os.system(cmd)

现在我已经完成了程序。我考虑过评论它们,但将所有这些不必要的打印(我无法删除所有 print 语句 - 因为有些为用户提供有用的信息)重定向到日志文件会更有用吗?任何技巧或提示。

【问题讨论】:

标签: python logging printing


【解决方案1】:

将您自己的类似文件放入sys.stdout 将让您通过print 捕获文本输出。

【讨论】:

  • 这是真的,但很糟糕,不应该使用。
【解决方案2】:

你应该看看python logging module


编辑:示例代码:

import logging

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, filename="logfile", filemode="a+",
                        format="%(asctime)-15s %(levelname)-8s %(message)s")
    logging.info("hello")

生成一个名为“logfile”的文件,内容如下:

2012-10-18 06:40:03,582 INFO     hello

【讨论】:

  • +1 用于日志记录模块。比打印语句为您提供更多控制权。
  • 您的解决方案实际上根本没有回答“如何重定向输出”的问题!转到该页面 - 搜索(徒劳)有关如何将日志记录重定向到文件的任何提示。实际的解决方案在 logging.config 的页面上——但我不同意你在那里找到它。 onlamp.com/pub/a/python/2005/06/02/logging.html 可能是一个更好的例子。
  • @TomSwirly 在页面底部:指向docs.python.org/library/… 的链接为您提供了一个解释FileHandler 的页面
  • @TomSwirly 和页面还解释了basicConfig
  • 你是对的,它在那个页面的底部,但是我错了,我改进了你的答案,所以它成功了!
【解决方案3】:

Python 允许您捕获和分配 sys.stdout(如前所述)来执行此操作:

import sys
old_stdout = sys.stdout

log_file = open("message.log","w")

sys.stdout = log_file

print "this will be written to message.log"

sys.stdout = old_stdout

log_file.close()

【讨论】:

  • 你也可以这样做 -- sys.stdout = sys.__stdout__ -- 而不是使用 old_stdout。
  • 这是一个混乱的 hack,但肯定有可能。如果您确实使用它,请将sys.stdout 重置为其在try/finallyfinally 块中的原始值。
  • @007brendan,假设sys.stdout 开始sys.__stdout__。这不是一个很好的假设,其他人可能会重定向 sys.stdout 用于这样的目的或更理智的用途,例如 整个应用程序的标准输出真的不应该是 @987654329 的系统@.
  • 我尝试了代码,但并没有真正起作用。这有什么问题? stackoverflow.com/questions/54049235/…
  • 有效! python3.6也可以,需要注意最后关闭打开的文件
【解决方案4】:

您可以将 sys.stdout 重定向替换为与 sys.stdout 具有相同接口的任何对象,在该对象的写入中,您也可以打印到终端和文件。例如看这个食谱http://code.activestate.com/recipes/119404-print-hook/

【讨论】:

  • 虽然适用,但该配方在风格、语义和概念上都很糟糕。
  • @Mike Graham,嘿,我是 8 年前写的 :),反正为什么这么糟糕?
  • 如果出于几个原因,我可能会避免使用类似的东西。它会更改全局值 (sys.stdout) 以供本地使用,并且可能会产生意外的、遥远的、意想不到的影响(这就是人们避免使用全局状态的原因)。完成后,它会将值恢复为sys.__stdout__,这可能是也可能不是sys.stdout 开始的内容,具体取决于其他人是否在做这种伎俩。它没有这样的用法,即意外的异常不会让sys.stdout 稍后停留在不需要的值上。
  • 话虽如此,我很抱歉我不文明。虽然我真诚地相信最好的解决方案不会使用这种技术,但我的批评过于严厉。
  • @Mike Graham 很好,批评很好,如果需要的话,这个钩子可以转移应用程序的所有打印,在实际情况下,我已经在一些打印乱七八糟的旧应用程序上使用它无处不在
【解决方案5】:

使用 logging 模块重定向 stdout 和 stderr 的简单方法如下: How do I duplicate sys.stdout to a log file in python?

【讨论】:

  • 该解决方案令人作呕,甚至不完全适用(因为它写入标准输出一个文件;OP 只想写入一个文件。)
  • 请你解释一下为什么这是“恶心”?我知道重定向 stdout 是一个坏主意,但有时值得这样做:本周我这样做是为了在一夜之间在服务器上运行 django 进行测试,并且 django 的 runserver 命令打印到 stdout。另外,请在发布之前测试您的意见,因为有问题的解决方案写入标准输出。我刚刚又测试了一遍。
  • 这很恶心,因为它使用了全局变量。这意味着当您阅读 print foo 时,如果不阅读全局更改的位置,它就不会按照您的预期进行,这甚至可能与 print 语句不在同一个文件中。它是非模块化的,因为很多事情不能都做到这一点。你甚至承认这是一个坏主意。当应该将某些内容打印到标准输出但您想重定向它时,有一些工具可以解决这个问题(例如 shell 上的>);当一些东西应该写在标准输出以外的地方时,你应该让你的代码写在那里。
  • 对于我关于将代码写入文件和标准输出的声明,我深表歉意。我正在与您链接的同一线程中查看不同的解决方案。我的错。
  • 已接受道歉。感谢您的澄清。我同意一个人应该避免弄乱全局变量。我更新了我原来的帖子,指出应该尽可能直接使用日志记录模块。这是我一直想要的,但直到现在才明确说出来。
【解决方案6】:
  • 下一次,如果你从一开始就使用logging 模块而不是使用print 语句,你会更开心。它提供了您想要的控制,您可以让它在您想要的位置写入标准输出。

  • 这里的许多人建议重定向标准输出。 这是一个丑陋的解决方案。 它改变了一个全局并且——更糟糕的是——它改变了它以供这个模块使用。我会尽快创建一个正则表达式,将所有 print foo 更改为 print >>my_file, foo 并将 my_file 设置为标准输出或我选择的实际文件。

    • 如果您的应用程序的任何其他部分实际上 依赖于写入标准输出(或者将来会写入但您还不知道),这会破坏它们。即使您不这样做,如果您错过了顶部的一小行,它也会使阅读您的模块看起来像是在做一件事,而实际上它在做另一件事。
    • Chevron 打印非常难看,但没有临时更改sys.stdout 的过程那么难看。
    • 从技术上讲,正则表达式替换无法做到这一点(例如,如果您在多行字符串文字内,它可能会产生误报)。但是,它很容易工作,请密切关注。
  • os.system 实际上总是不如使用subprocess 模块。后者不需要调用 shell,不会以通常不需要的方式传递信号,并且可以以非阻塞方式使用。

【讨论】:

    【解决方案7】:

    您可以创建一个日志文件并为写入做好准备。然后创建一个函数:

    def write_log(*args):
        line = ' '.join([str(a) for a in args])
        log_file.write(line+'\n')
        print(line)
    

    然后用 write_log() 替换你的 print() 函数名

    【讨论】:

      【解决方案8】:

      只是关于追加与写入模式的说明。如果您希望它替换日志文件,请将文件模式更改为“w”。我还必须注释掉流。然后使用 logging.info() 输出到指定的文件。

      if __name__ == '__main__':
          LOG_FORMAT = '%(asctime)s:%(levelname)s ==> %(message)s'
          logging.basicConfig(
              level=logging.INFO,
              filename="logfile",
              filemode="w",
              format=LOG_FORMAT
              #stream=sys.stdout
          )
      

      【讨论】:

        【解决方案9】:

        有很多方法可以将输出写入“.log”文件

        日志记录是一种跟踪某些文件运行时发生的事件的方法。也表明某些事件已经发生。

        import logging
        logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
        logging.debug('This is debug message')
        logging.info('This is information message')
        logging.warning('This is warning message')
        logging.error('This is warning message')
        

        另一种用于减少所有内容的方法,即您打印到控制台的所有内容都将保存到“日志”文件中

        python abc.py > abc.log
        

        通过使用这种方法,您可以将所有内容写入日志文件

        【讨论】:

          【解决方案10】:
          def log(txt):
              f = open(__file__ + '.log', "a")
              f.write(txt + '\r\n')
              f.close()
          

          用法:

          log('Hello World!')
          

          例子:

          python3 helloworld.py
          

          将附加到文件./helloworld.py.log。如果文件不存在,它将创建它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-01-01
            • 2012-10-13
            • 2012-01-03
            • 2018-07-03
            • 1970-01-01
            • 2018-01-09
            • 1970-01-01
            • 2021-10-10
            相关资源
            最近更新 更多