[英]Python using basicConfig method to log to console and file
I don't know why this code prints to the screen, but not to the file?我不知道为什么这段代码会打印到屏幕上,而不是打印到文件中? File "example1.log" is created, but nothing is written there.
文件“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')
I have "bypassed" this problem by creating a logging object, but it keeps bugging me why basicConfig()
approach failed?我通过创建日志对象“绕过”了这个问题,但它一直困扰着我为什么
basicConfig()
方法失败?
PS.附注。 If I change basicConfig call to:
如果我将 basicConfig 调用更改为:
logging.basicConfig(level=logging.DEBUG,
filename="example2.log",
format='%(asctime)s %(message)s',
handlers=[logging.StreamHandler()])
then all logs are in the file and nothing is displayed in the console.然后所有日志都在文件中,控制台中不显示任何内容。
Try this working fine(tested in python 2.7) for both console and file试试这个工作正常(在 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__)
I can't reproduce it on Python 3.3.我无法在 Python 3.3 上重现它。 The messages are written both to the screen and the
'example2.log'
.消息同时写入屏幕和
'example2.log'
。 On Python <3.3 it creates the file but it is empty.在 Python <3.3 上,它创建文件但它是空的。
The code:代码:
from logging_tree import printout # pip install logging_tree
printout()
shows that FileHandler()
is not attached to the root logger on Python <3.3.显示
FileHandler()
未附加到 Python <3.3 上的根记录器。
The docs for logging.basicConfig()
say that handlers
argument is added in Python 3.3. logging.basicConfig()
的文档说在 Python 3.3 中添加了handlers
参数。 The handlers
argument isn't mentioned in Python 3.2 documentation. Python 3.2 文档中没有提到
handlers
参数。
In the example below, you can specify the log destination based on its level.在下面的示例中,您可以根据级别指定日志目标。 For example, the code below lets all logs over the INFO level go to the log file, and all above ERROR level goes to the console.
例如,下面的代码让所有超过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')
Another technique using the basicConfig
is to setup all your handlers in the statement and retrieve them after the fact, as in...另一种使用
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)
More sensibly though is to construct your stream handler instance outside and configure them as standalone objects that you pass to the handlers list as in...更明智的是在外部构造您的流处理程序实例并将它们配置为您传递给处理程序列表的独立对象,如...
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])
WOOAH!哇!
I just spent about 20 minutes being baffled by this.我只是花了大约 20 分钟对此感到困惑。
Eventually I worked out that the StreamHandler
was outputting to stderr
, not stdout
(in a 'Doze DOS screen these have the same font colour!).最终我发现
StreamHandler
正在输出到stderr
,而不是stdout
(在“Doze DOS 屏幕中,它们具有相同的字体颜色!)。
This resulted in me being able to run the code perfectly OK and get sensible results, but in a pytest function things going awry.这导致我能够完美地运行代码并获得合理的结果,但是在 pytest 函数中事情出错了。 Until I changed from this:
直到我改变了这个:
out, _ = capsys.readouterr()
assert 'test message check on console' in out, f'out was |{out}|'
to this:对此:
_, err = capsys.readouterr()
assert 'test message check on console' in err, f'err was |{err}|'
NB the constructor of StreamHandler is注意 StreamHandler 的构造函数是
class logging.StreamHandler(stream=None)
and, as the docs say, "If stream is specified, the instance will use it for logging output; otherwise, sys.stderr will be used."并且,正如文档所说,“如果指定了流,则实例将使用它来记录输出;否则,将使用 sys.stderr。”
NB it seems that supplying the level
keyword does not run setLevel
on the handlers: you'd need to iterate on the resulting handlers and run setLevel
on each, if it matters to you.注意,似乎提供
level
关键字不会在处理程序上运行setLevel
:如果对您很重要,您需要迭代结果处理程序并在每个处理程序上运行setLevel
。
Reusable logger function.可重复使用的记录器功能。
def logger(logPath,fileName):
logging.basicConfig(
format='%(asctime)s - %(levelname)s - %(message)s',
level=logging.INFO,
handlers=[
logging.FileHandler("{0}/{1}.log".format(logPath,fileName)),
logging.StreamHandler()
])
return logging
On Other python file, import the logger
在其他 python 文件上,导入
logger
logger().info("this is info")
logger().critical('404')
logger().error("this is error")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.