我喜欢python日志记录基础架构,我想将它用于我运行的许多不同的夜间作业。很多这些工作使用模块X让我们说。我希望模块X的日志记录写入不依赖于模块X的日志文件,但是基于最终导致模块X中调用功能的作业。
因此,如果在模块X中,Later_script_1.py调用foo(),我希望foo()的日志转到overnight_script_1.log。我还希望通过使用once_script_2.py调用foo()来登录later_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 script1.py
python script2.py
并获取两个日志文件script1.log和script2.log,其中每个都记录模块X中发生的除零错误。
答案 0 :(得分:6)
我相信你应该遵循图书馆代码的标准设置:
假设您有一个包mypkg
,并且您希望此包记录信息,同时让包的用户决定使用哪种级别的日志记录以及输出应该去哪里。
mypkg
应该不设置日志级别或任何处理程序。
x
的模块mypkg
应该是这样的:
import logging
logger = logging.getLogger(__name__)
def my_function():
logger.info('something')
无法仅记录getLogger(__name__)
。
然后,使用script.py
并希望在控制台上登录级别mypkg
的{{1}}会执行以下操作:
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
作为INFO
,他可以这样做:
mypkg
如果您的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.py
,y.py
,a.py
和b.py
,并且您想要记录内部的功能c.py
的{{1}}和x
的{{1}}以及DEBUG
的{{1}}的{{1}}你可以通过设置相应的级别来实现记录器:
y
只将处理程序附加到WARNING
,一切都应该正常。
注意:在某些版本的python上,a/b/c.py
模块可能会警告您定义了一个没有库模块处理程序的记录器。要解决此问题,您可以使用仅删除日志消息的INFO
:
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
模块抱怨之外,logging
字面上什么都不做。 AFAIK新版本根本不需要这个。
答案 1 :(得分:-1)
您可以使用与您拥有的不同模块一样多的RotatingFileHandler并相应地设置其文件名
https://docs.python.org/2/library/logging.handlers.html
-Edit-
根据评论,您可能需要使用Formatter
来考虑调用的位置(了解对共享库的调用是来自module_1
还是{{1}等等)然后然后只需登录到同一个文件。
有一些需要考虑的注意事项:
https://docs.python.org/2/library/logging.html#formatter-objects https://docs.python.org/2/library/logging.html#logrecord-attributes https://docs.python.org/2.7/library/logging.config.html#configuration-file-format