# Logging
cur_flname = os.path.splitext(os.path.basename(__file__))[0]
LOG_FILENAME = constants.log_dir + os.sep + 'Log_' + cur_flname + '.txt'
util.make_dir_if_missing(constants.log_dir)
logging.basicConfig(filename=LOG_FILENAME, level=logging.INFO, filemode='w',
format='%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s',
datefmt="%m-%d %H:%M") # Logging levels are DEBUG, INFO, WARNING, ERROR, and CRITICAL
# Output to screen
logger = logging.getLogger(cur_flname)
logger.addHandler(logging.StreamHandler())
我使用上面的代码创建一个logger
,我可以在我的模块中使用它来同时将消息打印到屏幕上。
在Windows上,消息会输出到文件和屏幕。但是,在Mac OS X 10.9.5上,它们只能输出到文件。我使用的是Python 2.7。
有关如何解决此问题的任何想法?
答案 0 :(得分:3)
从你的问题很清楚,创建记录器名称没有问题, 日志文件名和记录到文件,因此我将简化此部分以保持我的代码简洁。
第一件事:对我来说,你的解决方案似乎正确logging.StreamHandler
默认情况下将输出发送到sys.stderr
。你可能有一些代码(不是
在您的问题中显示),正在修改sys.stderr
,或者您正在运行
以这种方式在OSX上的代码,没有显示输出到stderr(但是
真的输出)。
logging
将以下代码放入with_logging.py
:
import logging
import sys
logformat = "%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s"
datefmt = "%m-%d %H:%M"
logging.basicConfig(filename="app.log", level=logging.INFO, filemode="w",
format=logformat, datefmt=datefmt)
stream_handler = logging.StreamHandler(sys.stderr)
stream_handler.setFormatter(logging.Formatter(fmt=logformat, datefmt=datefmt))
logger = logging.getLogger("app")
logger.addHandler(stream_handler)
logger.info("information")
logger.warning("warning")
def fun():
logger.info(" fun inf")
logger.warning("fun warn")
if __name__ == "__main__":
fun()
运行它:$ python with_logging.py
,您将看到预期的日志记录(格式正确)
在日志文件app.log
和stderr
上。
请注意,如果您在stderr
上没有看到它,则会隐藏您的stderr
输出。要查看内容,请将StreamHandler
流更改为sys.stdout
。
logbook
logbook
是python包,提供替代日志记录方法。我在这里展示它以显示主要内容
与stdlib logging
的区别:对于logbook
,使用和配置对我来说似乎更简单。
with_logbook.py
import logbook
import sys
logformat = ("{record.time:%m-%d %H:%M} {record.level_name} {record.module} - "
"{record.func_name}: {record.message}")
kwargs = {"level": logbook.INFO, "format_string": logformat, "bubble": True}
logbook.StreamHandler(sys.stderr, **kwargs).push_application()
logbook.FileHandler("app.log", **kwargs).push_application()
logger = logbook.Logger("app")
logger.info("information")
logger.warning("warning")
def fun():
logger.info(" fun inf")
logger.warning("fun warn")
if __name__ == "__main__":
fun()
主要区别在于,您不必将处理程序附加到记录器,您的记录器只会发出 一些日志记录。
这些记录将由处理程序处理,如果它们已经到位。一种方法
是创建一个处理程序并在其上调用push_application()
。这将把
处理程序进入使用中的处理程序堆栈。
和以前一样,我们需要两个处理程序,一个用于文件,另一个用于stderr。
如果您运行此脚本$ python with_logbook.py
,您将看到完全相同的结果
记录。
short_logbook.py
使用stdlib logging
我真的不喜欢介绍性的舞蹈来使记录器工作。我想要
只需发出一些日志记录,并希望尽可能简单地做到这一点。
以下示例是对前一个示例的修改。而不是设置
在模块的最开头登录,我是在代码运行之前完成的
- 在if __name__ == "__main__"
内(你可以在任何其他方面做同样的事情
位)。
出于实际原因,我将模块和调用代码分成两个文件:
档案funmodule.py
from logbook import Logger
log = Logger(__name__)
log.info("information")
log.warning("warning")
def fun():
log.info(" fun inf")
log.warning("fun warn")
您可以注意到,实际上只有两行与制作相关 可用的记录。
然后,创建调用代码,放入short_logbook.py
:
import sys
import logbook
if __name__ == "__main__":
logformat = ("{record.time:%m-%d %H:%M} {record.level_name} {record.module}"
"- {record.func_name}: {record.message}")
kwargs = {"level": logbook.INFO, "format_string": logformat, "bubble": True}
logbook.StreamHandler(sys.stderr, **kwargs).push_application()
logbook.FileHandler("app.log", **kwargs).push_application()
from funmodule import fun
fun()
运行代码,您将看到它与以前一样工作,只有记录器名称为funmodule
。
请注意,我在设置日志记录后执行了from funmodule import fun
。如果我做了
如果short_logbook.py
文件为top,则不会显示funmodule.py
中的前两个日志记录
因为它们在模块导入期间发生。
编辑:添加了另一个logging
解决方案以进行公平比较
logging
解决方案尝试对logbook
和logging
进行公平比较我将最终logbook
示例重写为
logging
。
funmodule_logging.py
看起来像:
import logging
log = logging.getLogger(__name__)
log.info("information")
log.warning("warning")
def fun():
log.info(" fun inf")
log.warning("fun warn")
log.error("no fun at all")
和short_logging.py
如下所示:
import sys
import logging
if __name__ == "__main__":
logformat = "%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s"
datefmt = "%m-%d %H:%M"
logging.basicConfig(filename="app.log", level=logging.INFO, filemode="w",
format=logformat, datefmt=datefmt)
stream_handler = logging.StreamHandler(sys.stderr)
stream_handler.setFormatter(logging.Formatter(fmt=logformat, datefmt=datefmt))
logger = logging.getLogger("funmodule_logging")
logger.addHandler(stream_handler)
from funmodule_logging import fun
fun()
功能非常相似。
我仍然记录着日志。 stdlib logging
不容易掌握,但它在stdlib并提供
一些很好的东西,比如logging.config.dictConfig
允许通过字典配置日志记录。
logbook
开始时要简单得多,但目前有点慢,缺乏
dictConfig。无论如何,这些差异与您的问题无关。