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

时间:2016-10-12 14:14:24

标签: python logging

我喜欢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中发生的除零错误。

2 个答案:

答案 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) 包含模块mypkgx.pyy.pya.pyb.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}等等)然后然后只需登录到同一个文件。

有一些需要考虑的注意事项:

  • 我不确定文件写入是否保留订单,因为可能有两个或更多进程写入该文件
  • 日志文件的大小可能会随着0磁盘空间的增加而增加

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