内置python的__import__ vs imp.load_module:ValueError:尝试相对导入超出toplevel包

时间:2017-01-29 12:52:56

标签: python python-2.7 python-import relative-import

我有一段动态导入大量子包的代码 - 包结构:

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__的文档中很常见,在那里我们读到:

  

该函数导入模块名称,可能使用给定的globals和locals来确定如何解释包上下文中的名称。 fromlist给出了应该从name给出的模块导入的对象或子模块的名称。标准实现根本不使用其locals参数,并仅使用其全局变量来确定import语句的包上下文

所以:

  • 是否可以使用不同的参数集调用imp.load_module,以便让它知道顶级包确实不是游戏/ gameX?

相关:

0 个答案:

没有答案