尝试在同一目录中加载模块的动态导入模块的ImportError

时间:2013-11-25 19:12:43

标签: python python-2.7 import

考虑以下设置:

[~/test]$ tree .
.
├── main.py
└── pkg
    ├── a.py
    ├── b.py
    ├── c.py
    └── __init__.py

1 directory, 5 files
[~/test]$ cat main.py 
from pkg import a

[~/test]$ cat pkg/a.py 
print "Importing b using import statement"
import b

print "\nImporting b dynamically"
import imp
import os
b = imp.load_source('b', os.path.dirname(__file__) + '/b.py')

[~/test]$ cat pkg/b.py 
import c

[~/test]$ cat pkg/c.py 
print 'Hello from c.py'

我期望的行为是,即使动态导入b.py,b.py中的import c行也能正常工作,因此此代码将提供以下内容:

[~/test]$ python main.py
Importing b using import statement
Hello from c.py

Importing b dynamically
Hello from c.py

但是我得到以下内容:

[~/test]$ python main.py
Importing b using import statement
Hello from c.py

Importing b dynamically
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from pkg import a
  File "/home/f.j/test/pkg/a.py", line 8, in <module>
    b = imp.load_source('b', os.path.dirname(__file__) + '/b.py')
  File "/home/f.j/test/pkg/b.py", line 1, in <module>
    import c
ImportError: No module named c

所以问题在这里:

  • 为什么动态导入模块时行为会有所不同?
  • 我是否可以在a.py中进行任何更改 ,以便即使动态导入b.py,b.py中的import c语句也能正常运行?

请注意,我可以通过将b.py中的import语句更改为from pkg import c来实现此功能,但我不想这样做。这里的期望是模块应始终能够直接导入其中包含的其他模块,而无需指定完整的包位置或操纵sys.path

我已经在a.py中尝试了以下内容:

# this gives the same behavior as imp.load_source
b = imp.load_module('b', *imp.find_module('b', [os.path.dirname(__file__)]))

# with this I get 'ImportError: No module named b'
b = __import__('b')

2 个答案:

答案 0 :(得分:4)

您正在动态导入顶级模块 b,这是与pkg/b不同的模块。

由于sys.path不包含/home/f.j/test/pkg,因此c找不到bc正在尝试导入顶级模块pkg.b那一刻。另一方面,c模块会尝试首先找到顶级模块pkg.c,然后找到本地pkg.b

而是导入b = imp.load_source('pkg.b', os.path.dirname(__file__) + '/b.py')

{{1}}

答案 1 :(得分:1)

我怀疑问题是b.py不理解它是'pkg'的一部分,并且相对路径用于通用导入。

您可以通过将 b.py 修改为:

来导入c
from pkg import c

更正确的是,您可以通过修改 b.py 来说明 b.py 它是 pkg 的一部分:

__package__ = 'pkg'
import c

我会非常有兴趣了解为什么你需要首先做这件事,因为这看起来很可怕。