我有一個基於配置動態導入模塊的腳本。我試圖在腳本上實現守護程序上下文(使用python-daemon
模塊),它似乎干擾了python查找有問題的模塊的能力。python importlib在守護程序上下文中找不到模塊
Insite的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
不變,守護程序上下文不清除environemnt或chrooting。當然,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")
這些模塊都做不同的事情。有些碰巧打開文件或打開偵聽端口。我已經檢查過了,DaemonContext並沒有把我放入chroot中。默認情況下,它並沒有這樣做,並且我在沒有發生的問題中指出。我已經比較了開放環境之前和之後儘可能多的環境,唯一的區別是CWD更改爲/。運行sscce,你可以檢查。 – mpounsett
「這些模塊都做不同的事情,有些打開文件或打開偵聽端口。」 - 如果他們將其作爲進口時的副作用,則設計不佳,應該修復它們。編寫一個可以單獨調用的功能,以便在需要時打開端口/文件。 – Kevin
另外,如果它不會將你置入chroot,那麼'files_preserve'參數在做什麼呢? – Kevin