Python包结构
我有一个Python包,里面有几个子包。
myproject/
__init__.py
models/
__init__.py
...
controllers/
__init__.py
..
scripts/
__init__.py
myscript.py
在myproject.scripts.myscript这个地方,我怎么才能访问到myproject.models呢?我试过
from myproject import models # No module named myproject
import models # No module named models
from .. import models # Attempted relative import in non-package
我之前也遇到过这个问题,但我总是记不住该怎么做。对我来说,这实在是太不直观了。
2 个回答
你的项目不在你的路径中。
选项 A
- 安装你的包,这样 Python 就可以在任何地方通过它的绝对名称找到它(使用
from myproject import models
)
选项 B
- 使用一些小技巧,把上级目录添加到你的路径中
sys.path.append(os.path.abspath('..'))
推荐使用第一个选项。
这是正确的版本:
from myproject import models
如果出现 ImportError: No module named foo
的错误,那是因为你没有设置 PYTHONPATH
,导致它没有包含包含 myproject/
的目录。
我担心其他人会建议一些技巧,让你避免设置 PYTHONPATH
。我建议你不要听他们的。这就是 PYTHONPATH
存在的原因:告诉 Python 到哪里去找要加载的代码。它是可靠的,文档也写得比较清楚,而且可以在很多环境中使用。那些人为了避免设置它而使用的技巧,都不具备这些优点。
即使没有设置 PYTHONPATH
,明确的相对导入是可以工作的,因为它可以沿着目录结构向上查找,直到找到正确的位置,而不需要先找到顶层再向下查找。不过,如果你把脚本作为命令行参数传给 python
(或者直接用 #!/usr/bin/python
这一行调用),这个方法就不行了。这是因为在这两种情况下,它会成为进程的 __main__
模块。对于 __main__
来说,没有地方可以向上走——它已经在顶层了!如果你通过 导入 这个模块来调用你脚本中的代码,那就没问题。也就是说,比较一下:
python myproject/scripts/myscript.py
和
python -c 'import myproject.scripts.myscript'
你可以利用这一点,不直接执行你的脚本模块,而是创建一个 bin/myscript
,在里面进行导入,并可能调用一个主函数:
import myprojects.scripts.myscript
myprojects.scripts.myscript.main()
可以参考 Twisted 的命令行脚本是如何定义的: http://twistedmatrix.com/trac/browser/trunk/bin/twistd