我有一个基于配置动态导入模块的脚本。我正在尝试python-daemon
在脚本上实现一个守护进程上下文(使用模块),它似乎干扰了 python 找到有问题的模块的能力。
我这样mymodule/__init__.py
做setup()
:
load_modules(args, config, logger)
try:
with daemon.DaemonContext(
files_preserve = getLogfileHandlers(logger)
):
main_loop(config)
我接到了setup()
里面的电话mymodule/__main__.py
,我正在以这种方式加载整个内容:
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
没有改变,守护进程上下文没有清除环境或 chrooting。cwd 当然会更改为/
,但这不应该对 python 查找模块的能力产生任何影响,因为绝对路径.
出现在sys.path
.
我在这里想念什么?
编辑:我正在添加一个SSCCE以使情况更加清晰。以下三个文件创建了一个名为“mymodule”的模块,可以从命令行以PYTHONPATH=. python -m mymodule
. 有两个调用load_module()
in __init__.py
,一个被注释掉。您可以通过交换评论中的哪一个来证明问题。
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")