87

我不知道为什么这段代码会打印到屏幕上,而不是文件上?文件“example1.log”已创建,但没有写入任何内容。

#!/usr/bin/env python3
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(message)s',
                    handlers=[logging.FileHandler("example1.log"),
                              logging.StreamHandler()])
logging.debug('This message should go to the log file and to the console')
logging.info('So should this')
logging.warning('And this, too')

我通过创建一个日志对象“绕过”了这个问题,但它一直困扰着我为什么basicConfig()方法失败了?

PS。如果我将 basicConfig 调用更改为:

logging.basicConfig(level=logging.DEBUG,
                    filename="example2.log",
                    format='%(asctime)s %(message)s',
                    handlers=[logging.StreamHandler()])

然后所有日志都在文件中,控制台中不显示任何内容。

4

5 回答 5

58

试试这个工作正常(在python 2.7中测试)控制台和文件

# set up logging to file
logging.basicConfig(
     filename='log_file_name.log',
     level=logging.INFO, 
     format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
     datefmt='%H:%M:%S'
 )

# set up logging to console
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
# set a format which is simpler for console use
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
# add the handler to the root logger
logging.getLogger('').addHandler(console)

logger = logging.getLogger(__name__)
于 2014-05-15T14:43:49.190 回答
28

我无法在 Python 3.3 上重现它。消息同时写入屏幕和'example2.log'. 在 Python <3.3 上,它会创建文件,但它是空的。

编码:

from logging_tree import printout  # pip install logging_tree
printout()

显示FileHandler()未附加到 Python <3.3 上的根记录器。

文档logging.basicConfig()说该handlers参数是在 Python 3.3 中添加的。handlersPython 3.2 文档中没有提到该参数。

于 2012-11-20T18:14:05.630 回答
9

在下面的示例中,您可以根据其级别指定日志目标。例如,下面的代码让INFO级别以上的所有日志都进入日志文件,而ERROR级别以上的所有日志都进入控制台。

import logging
logging.root.handlers = []
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO , filename='ex.log')

# set up logging to console
console = logging.StreamHandler()
console.setLevel(logging.ERROR)
# set a format which is simpler for console use
formatter = logging.Formatter('%(asctime)s : %(levelname)s : %(message)s')
console.setFormatter(formatter)
logging.getLogger("").addHandler(console)

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.exception('exp')
于 2016-07-27T12:37:36.400 回答
7

使用的另一种技术basicConfig是在语句中设置所有处理程序并在事后检索它们,如...

import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s',
                    handlers=[logging.FileHandler("my_log.log", mode='w'),
                              logging.StreamHandler()])
stream_handler = [h for h in logging.root.handlers if isinstance(h , logging.StreamHandler)][0]
stream_handler.setLevel(logging.INFO)

更明智的做法是在外部构造流处理程序实例并将它们配置为独立对象,然后将它们传递给处理程序列表,如...

import logging

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s',
                    handlers=[logging.FileHandler("my_log.log", mode='w'),
                              stream_handler])
于 2019-11-13T00:05:41.613 回答
1

哇!

我只花了大约 20 分钟的时间对此感到困惑。

最终我发现StreamHandler正在输出到stderr,而不是stdout(在“打盹 DOS 屏幕中,它们具有相同的字体颜色!)。

这导致我能够完美地运行代码并获得合理的结果,但是在 pytest 函数中事情出错了。直到我改变了这个:

out, _ = capsys.readouterr()
assert 'test message check on console' in out, f'out was |{out}|'

对此:

_, err = capsys.readouterr()
assert 'test message check on console' in err, f'err was |{err}|'

注意 StreamHandler 的构造函数是

class logging.StreamHandler(stream=None)

并且,正如文档所说,“如果指定了流,则实例将使用它来记录输出;否则,将使用 sys.stderr。”

注意似乎提供level关键字不会setLevel在处理程序上运行:如果对您很重要,您需要迭代生成的处理程序并setLevel在每个处理程序上运行。

于 2021-10-24T11:22:16.657 回答