同一包中的绝对导入模块
我把我的导入问题简化成了一个简单的基本案例。假设我有一个Python包:
mypkg/
__init__.py
a.py
b.py
a.py文件里包含:
def echo(msg):
return msg
b.py文件里包含:
from mypkg import a # possibility 1, doesn't work
#import a # possibility 2, works
#from mypkg.a import echo # import also fails
print(a.echo())
当我运行 python b.py
时,在Python 2.7.6和Python 3.3.5上都会出现 ImportError: No module named mypkg
的错误。我也尝试在这两种情况下都加上 from __future__ import absolute_import
,结果还是一样的问题。
预期结果:
我希望可能性1能正常工作。
我为什么想这样做:
可能性2就不太理想了。假设标准库可能会引入一个叫 a
的包(虽然这种情况不太可能,但你明白我的意思)。在Python 2中,它会先搜索当前包,而Python 3及以上版本则做了绝对导入的修改,会先检查标准库。无论我有什么理由,可能性1应该是能工作的,对吧?我敢肯定我以前做过成千上万次。
注意:如果你在 mypkg
外部写一个脚本, from mypkg import a
是没有问题的。
我的问题类似于python - 同目录下模块的绝对导入,但作者暗示我现在的做法应该是可以工作的。
4 个回答
试试这个:
import sys
import os
this_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.dirname(this_dir))
from mypkg import a
print(a.echo())
我觉得问题出在你在 mypkg 文件夹里没有对 mypkg 的引用。看看当我尝试运行你的例子时,Python 是怎么做的(使用详细模式):
# trying /vagrant/mypkg/mypkg.py
这就是为什么它能找到这个模块,因为它并不存在。你可以用一个小技巧,就是创建一个叫 mypkg.py 的文件,里面写上这一行:
import a
但这其实只是你上面提到的第二种可能性换了个形式。如果不知道你想要实现什么,我会选择 包内引用 文本中的第一个例子。我会这样写 b.py:
from a import echo
print(echo('message'))
是的,这样是行不通的,因为当你调用 print(mypkg.a.echo())
时,mypkg
还在加载中(mypkg.__init__
-> mypkg.b
)。这是因为Python会先加载父模块。你可以查看这个链接了解更多:https://docs.python.org/3/reference/import.html#searching
你可以把 print(mypkg.a.echo())
放到一个函数里:
def echo():
mypkg.a.echo()
然后:
import mypkg.b
mypkg.b.echo()
或者甚至:
print(sys.modules['mypkg.a'].echo())
另外,你也可以帮助Python找到你的模块:
import importlib
mypkg.a = importlib.import_module('mypkg.a')
mypkg.a.echo()
使用from mypkg import a
是正确的写法。不要在Python包的目录里面直接运行脚本,这样会让同一个模块用不同的名字出现,可能会导致错误。应该在包含mypkg
的目录下运行python -m mypkg.b
。
如果想要在任何目录下都能运行,mypkg
需要放在pythonpath里面。