我有一段代码可以动态导入一堆子包 - 包结构:
main_package/
code_below_is_here.py
game/
__init__.py
game1/
__init__.py
constants.py
records.py
...
game2/
__init__.py
constants.py
records.py
...
使用该__import__
函数(免责声明:我没有编写该代码,我只是当前的维护者):
import pkgutil
import game as game_init# <----- I import the game/ package
# Detect the known games
for importer,modname,ispkg in pkgutil.iter_modules(game_init.__path__):
if not ispkg: continue # game support modules are packages
# Equivalent of "from game import <modname>"
try:
module = __import__('game',globals(),locals(),[modname],-1)
except ImportError:
continue
这工作得很好。
现在我试图用imp.load_module
做同样的事情(试图回答我的另一个问题):
for importer, modname, ispkg in pkgutil.iter_modules(game_init.__path__):
if not ispkg: continue # game support modules are packages
# Equivalent of "from game import <modname>"
+ init_file, pathname, description = imp.find_module(modname, game_init.__path__)
try:
- module = __import__('game',globals(),locals(),[modname],-1)
+ module = imp.load_module(modname, init_file, pathname, description)
except ImportError:
deprint(u'Error in game support module:', modname, traceback=True)
continue
+ finally:
+ if init_file is not None: init_file.close()
但这失败了:
Traceback (most recent call last):
...
File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\bash\bush.py", line 64, in _supportedGames
module = imp.load_module(modname, init_file, pathname, description)
File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\bash\game\fallout4\__init__.py", line 32, in <module>
from .records import MreHeader, MreLvli, MreLvln
File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\bash\game\fallout4\records.py", line 26, in <module>
from ..skyrim.records import MelBounds, MreLeveledList
ValueError: Attempted relative import beyond toplevel package
我想答案在__import__
's docs 的某个地方,我们在其中读到:
该函数导入模块名称,可能使用给定的全局变量和局部变量来确定如何在包上下文中解释名称。fromlist 给出了应该从 name 给定的模块导入的对象或子模块的名称。标准实现根本不使用它的 locals 参数,并且只使用它的 globals 来确定 import 语句的包上下文。
所以:
- 是否可以
imp.load_module
使用一组不同的参数进行调用,以便知道顶级包确实不是 game/gameX ?
有关的: