gpt4 book ai didi

由不同脚本共享的模块的 Python 日志记录

转载 作者:太空狗 更新时间:2023-10-30 02:27:39 29 4
gpt4 key购买 nike

我喜欢 python 日志记录基础设施,我想将它用于我运行的许多不同的通宵工作。比方说,很多这些工作都使用模块 X。我希望模块 X 的日志记录写入不依赖于模块 X 的日志文件,而是基于最终导致调用模块 X 中的功能的作业。

因此,如果 nightnight_script_1.py 在模块 X 中调用 foo(),我希望 foo() 的日志转到 nightnight_script_1.log。我还希望 overnight_script_2.py 对 foo() 的调用记录到 overnight_script_2.log。

此问题的一个潜在解决方案是根据查看 sys.argv 的第 0 个参数来设置日志文件,该参数可以映射到我的首选文件。以这种方式做这件事似乎有点老套。这样做有首选的设计模式吗?我不想根据调用函数的模块翻阅不同的日志文件来查找我的一个脚本的诊断信息。这是一些代码,因为我不确定我是否说清楚了。

这里是script1.py

import X
import logging_utils as lu
import sys

logname=sys.argv[0][:-3] # logname==script1 with the .py cut off
logger=lu.setup_logger(log_name) # assume this does the formatting and sets the filehandlers
# furthermore assume the file handler is set so that the output goes to script1.log.

# do a bunch of thing
logger.info('I am doing a bunch of things in script1 and I will now call X.foo()')
X.foo() # see module X below
logger.info('I finished X.foo()')

同理,这里是script2.py

import X
import logging_utils as lu
import sys

logname=sys.argv[0][:-3] # logname==script2 with the .py cut off
logger=lu.setup_logger(log_name) # assume this does the formatting and sets the filehandlers
# furthermore assume the file handler is set so that the output goes to script2.log.

# do a bunch of thing
logger.info('I am doing a bunch of things in script2 and I will now call X.foo()')
X.foo() # see module X below
logger.info('I finished X.foo()')

这是X.py

import logging
import sys
logname=sys.argv[0][:-3] # could be script1 or script2
logger=logging.getLogger(logname)

def foo():
try:
i=1/0
except:
logger.error('oops - division by zero')

然后我要运行:

python脚本1.py

python脚本2.py

并得到两个日志文件 script1.log 和 script2.log,其中分别记录了模块 X 中发生的被零除错误。

最佳答案

我相信您应该只遵循库代码的标准设置:

假设您有一个包 mypkg,并且您希望这个包记录信息,同时让包的用户决定使用哪个级别的日志记录以及输出的位置。

mypkg 不应 设置日志级别或任何处理程序。mypkg 的模块 x 应该是这样的:

import logging

logger = logging.getLogger(__name__)


def my_function():
logger.info('something')

没有任何日志记录的配置只是 getLogger(__name__)

然后您的 script.py 使用 mypkg 并希望在控制台上以 INFO 级别登录将执行:

import logging
import mypkg

root_logger = logging.getLogger()
console_handler = logging.StreamHandler()

root_logger.setLevel(logging.INFO)
root_logger.addHandler(console_handler)

mypkg.my_function() # produces output to stderr

虽然 script2.py 将在 DEBUG 级别记录到文件:

import logging
import mypkg


root_logger = logging.getLogger()
file_handler = logging.FileHandler('some_file.log')

root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(file_handler)

mypkg.my_function()

请注意,通过在根记录器上设置级别和处理程序,我们正在“全局”设置级别。如果用户有一些自己的记录器,他想使用 DEBUG 级别,但他想为 mypkg 使用级别 INFO 他可以这样做:

root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)

mypkg_logger = logging.getLogger('mypkg')
mypkg_logger.setLevel(logging.INFO)

handler = #... whatever you want
root_logger.addHandler(handler)

如果您的 mypkg 包含模块 x.pyy.pya.pyb.pyc.py 并且您想在 DEBUG 中记录 x 中的函数>yWARNINGa/b/c.pyINFO 你可以通过设置级别来做到这一点相应的记录器:

mypkg_logger = logging.getLogger('mypkg')
my_pkg_logger.setLevel(logging.INFO)

x_logger = logging.getLogger('mypkg.x')
x_logger.setLevel(logging.DEBUG)
y_logger = logging.getLogger('mypkg.y')
y_logger.setLevel(logging.WARNING)

将处理程序仅附加到 root_logger,一切都会正常工作。


注意:在某些版本的 python 上,logging 模块可能会警告您,您定义了一个没有库模块处理程序的记录器。要解决此问题,您可以使用仅删除日志消息的 NullHandler:

# x.py

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

所以 NullHandler 除了防止 logging 模块提示外,实际上什么都不做。 AFAIK 较新的版本根本不需要这个。

关于由不同脚本共享的模块的 Python 日志记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40000929/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com