【发布时间】:2015-04-12 22:06:39
【问题描述】:
我有一个基于配置动态导入模块的脚本。我正在尝试在脚本上实现一个守护进程上下文(使用python-daemon 模块),它似乎干扰了python 查找相关模块的能力。
在setup() 中的mymodule/__init__.py 我这样做:
load_modules(args, config, logger)
try:
with daemon.DaemonContext(
files_preserve = getLogfileHandlers(logger)
):
main_loop(config)
我在mymodule/__main__.py 内接到了setup() 的电话,我正在以这种方式加载整个内容:
PYTHONPATH=. python -m mymodule
这很好用,但是在 load_modules() 中设置的侦听端口被新添加的守护程序上下文关闭,所以我想像这样在守护程序上下文中移动该函数调用:
try:
with daemon.DaemonContext(
files_preserve = getLogfileHandlers(logger)
):
load_modules(args, config, logger)
main_loop(config)
模块以这种方式在load_modules() 中加载:
for mysubmodule in modules:
try:
i = importlib.import_module("mymodule.{}".format(mysubmodule))
except ImportError as err:
logger.error("import of mymodule.{} failed: {}".format(
mysubmodule, err))
在守护进程上下文之外使用load_modules() 可以正常工作。当我将它移动到守护进程上下文中时,它似乎无法找到它正在寻找的模块。我明白了:
import of mymodule.submodule failed: No module named submodule
这看起来像是某种命名空间问题——我注意到异常只涉及我尝试导入的模块名称的子模块部分——但我已经比较了我在守护进程上下文内外所能想到的所有内容,我找不到重要的区别。 sys.path 没有改变,守护进程上下文没有清除环境或 chroot。 cwd 当然会更改为/,但这不应该对python 查找模块的能力产生任何影响,因为. 的绝对路径出现在sys.path 中。
我在这里错过了什么?
编辑:我添加了一个SSCCE 以使情况更清楚。以下三个文件创建了一个名为“mymodule”的模块,可以从命令行以PYTHONPATH=. python -m mymodule 运行。在__init__.py 中有两个对load_module() 的调用,一个被注释掉了。您可以通过交换评论来证明问题。
mymodule/__main__.py
from mymodule import setup
import sys
if __name__ == "__main__":
sys.exit(setup())
mymodule/__init__.py
import daemon
import importlib
import logging
def main_loop():
logger = logging.getLogger('loop')
logger.debug("Code runs here.")
def load_module():
logger = logging.getLogger('load_module')
submodule = 'foo'
try:
i = importlib.import_module("mymodule.{}".format(submodule))
except ImportError as e:
logger.error("import of mymodule.{} failed: {}".format(
submodule, e))
def setup_logging():
logfile = 'mymodule.log'
fh = logging.FileHandler(logfile)
root_logger = logging.getLogger()
root_logger.addHandler(fh)
root_logger.setLevel(logging.DEBUG)
def get_logfile_handlers(logger):
handlers = []
for handler in logger.handlers:
handlers.append(handler.stream.fileno())
return handlers
def setup():
setup_logging()
logger = logging.getLogger()
# load_module()
with daemon.DaemonContext(
files_preserve = get_logfile_handlers(logger)
):
load_module()
main_loop()
mymodule/foo.py
import logging
logger=logging.getLogger('foo')
logger.debug("Inside foo.py")
【问题讨论】:
标签: python python-2.7 python-daemon python-importlib