Python 3中的动态导入+相对导入

时间:2011-02-22 13:14:22

标签: python import python-3.x

我有一个 Python 3 项目,我使用imp.load_module从磁盘动态导入模块。但是,当相对导入发生在动态导入的模块中时,我遇到了相对导入失败的问题。

根据我的阅读,我得出的结论是,在确定默认导入器时,默认导入器仅使用__file____path____package____name__进口的路径。然而,我已在下面的代码中验证了这些,并且在动态导入时仍然失败。 (它在解释器中导入时使用更新的sys.path

# File structure:
# [root]
#  ├─ __init__.py
#  ├─ board.py
#  └─ test.py

# Contents of 'board.py':
import os, sys
import root  # Already imported... just need a reference

ROOT_DIR = os.path.dirname(root.__file__)
assert root is sys.modules['root']
assert root.__package__ is None
assert root.__name__ == 'root'
assert root.__file__ == os.path.join(ROOT_DIR, '__init__.py')
assert not hasattr(root, '__path__')

xx = object()
assert xx is sys.modules['root.board'].xx
assert __package__ is None
assert __name__ == 'root.board'
assert __file__ == os.path.join(ROOT_DIR, 'board.py')
assert not hasattr(sys.modules['root.board'], '__path__')

assert os.path.isfile(os.path.join(ROOT_DIR, 'test.py'))
from . import test  # ImportError('cannot import name test',)

但是如果我在导入失败之前攻击sys.path并重新导入当前包,它就会起作用:

oldroot = root
del sys.modules['root']
sys.path.append(os.path.dirname(ROOT_DIR))
import root
from . import test  # No error here

此外,上面提到的四个黄金属性在新旧包中都是相同的:

assert oldroot.__package__ == root.__package__
assert oldroot.__name__ == root.__name__
assert oldroot.__file__ == root.__file__
assert not hasattr(root, '__path__')

这意味着__package____name____file____path__不能完整。是否有Python用于定位导入的其他属性?我忽略了什么会导致导入失败?

1 个答案:

答案 0 :(得分:1)

缺少root.__path__值是可疑的(这意味着Python不会将root视为包)。

使用类型值load_module()(模块)而不是第一个类型为1(包)的5调用的事实也是非常可疑。

您是否使用imp.find_module()来计算imp.load_module()来电的正确输入?

对于包,imp.load_module()的输入应如下所示:

# demo is a package in the current directory for this example
>>> info = imp.find_module('demo')
>>> info
(None, 'demo', ('', '', 5))
>>> demo = imp.load_module('demo', *info)
>>> demo.__path__
['demo']