我的python应用程序由主程序和几个模块组成。每个模块都包含
import logging
log = logging.getLogger('myapp.mymodule')
在全球范围内。处理程序和其他在主程序中初始化的东西,通常所有消息都转发到syslog。
现在我想启动多个应用程序实例(具有实例名称的配置文件可以指定为命令行参数)。问题是:如何将实例名称传递给每个导入的模块?我希望记录器名称看起来像'myappinstance.mymodule'或'myapp.instance.module'。我不想在每个模块中搞乱配置文件解析,因为这需要硬编码的配置路径。
答案 0 :(得分:2)
这是我能想到的解决方案:
在主程序中,设置名为myapp
import logging
logger = logging.getLogger("myapp")
formatter = logging.Formatter("%(asctime)s - instance_name - %(levelname)s - %(message)s")
ch = logging.SysLogHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)
然后,使用记录器myapp.*
的所有导入模块将在记录消息中包含instance_name。
答案 1 :(得分:0)
好吧,描述问题确实有助于解决它:)只是想过使用环境变量来传递所有模块的参数:
main.py:
import os
os.environ['instance'] = 'blah'
import a
a.py:
import os
import b
print 'a:', os.environ['instance']
b.py:
import os
print 'b:', os.environ['instance']
$ python main.py
b: blah
a: blah
对于这个的任何其他想法或批评者?
答案 2 :(得分:0)
只需编写您自己的日志包装器,它将为您提供正确的名称(根据需要进行调整以获得您想要的实例名称):
def get_logger(obj=None):
if isinstance(obj, str):
return logging.getLogger(obj)
elif obj is not None:
logger_name ="%s.%s" % (obj.__class__.__module__, obj.__class__.__name__)
return logging.getLogger(logger_name)
else:
return logging.getLogger()
class Foo(object):
def __init__(self):
self._log = get_logger(self)
或者,如果进程ID足够好,只需在格式化程序中使用它:
http://www.python.org/doc/2.5.4/lib/node421.html
formatter = logging.Formatter("%(process)d - %(asctime)s - %(levelname)s - %(message)s")
显然,这将唯一地标识每个进程,但不会提供与实例相关的任何内容。