我通过map(__import__, 'scripts.myscript')
trick动态加载python模块。我正在父模块中配置记录器,并且登录父模块工作正常。但是,动态加载的模块中的任何日志记录都会向stderr返回以下消息:
No handlers could be found for logger
我唯一的解决方法是将动态加载的模块logger
属性设置为父模块的logger
属性; e.g:
logger = logging.getLogger(__name_)
# ... configure logger
script = map(__import__, 'scripts.myscript')[0]
script.myscript.logger = logger
是否有一种更好的方法可以让动态加载的模块接受父级中记录器的设置?
顺便说一下,为什么在动态导入这样的模块时,不会发生正常的记录器传播?
我的项目结构:
/app
/app
config.py
...
/scripts
myscript.py
...
script.py
在script.py
中,我动态加载myscript.py
,类似于以下内容:
import logging
import sys
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# get 'myscript' from args
script_name = sys.argv[1]
script = map(__import__, ['scripts.{}'.format(script_name)])[0]
# The workaround is to set the dynamic module's logger attribute
# to the parent module's attribute, like this:
# getattr(script, script_name).logger = logger
# call main() function in myscript.py
errno = getattr(script, script_name).main()
# This is logged successfully
logger.info("Errno from {} is {}".format(script_name, errno)
myscript.py
有类似于以下内容的内容:
from app.config import * # See note below
import logging
logger = logging.getLogger(__name__)
def main():
# This results in: No handlers could be found for logger
logger.info("Hello world")
return 0
如果有人想知道为什么我首先要经历所有这些麻烦,那是因为上面的项目结构。我希望scripts
目录与app
目录位于同一级别,但我希望各个脚本可以访问app/config.py
模块。我不想修改单个脚本中的python / sys路径,我也不想将应用程序安装到站点包中。我也喜欢所有脚本都有一个入口点script.py
。