Python子模块内部引用——它们真的是疯狂的吗?
抱歉提前问了个新手问题。我有点搞不懂这个,文档也没帮上忙!
考虑一下下面这个文件夹结构:
spam.py
foo / __init__.py
ham.py
eggs.py
还有以下这段代码:
# __init__.py
# blank
# ham.py
print( "got ham!" )
# eggs.py
print( "got eggs, importing ham!" )
import foo.ham
现在,如果我在 spam.py
里面使用 import foo.eggs
,一切都正常,所有模块的引用都能正常工作。
但是
如果我直接执行 eggs.py
,我就会遇到一个错误:ImportError: No module named foo.ham
!如果我把 foo.ham
的引用改成只用 ham
,那就能正常工作了……但这样我就不能 import foo.eggs
了!
那么,我该怎么开发 eggs
呢?如果我用不带点的引用,开发是没问题的,但我无法尝试,因为我不能 import
这个模块!如果我用完整的 foo.ham
引用,我可以导入这个包,但又无法执行子模块进行开发!
这是Python的打包结构出了问题吗?我是不是做错了什么?
3 个回答
这是Python的打包结构。通常,一个模块可以通过点号引用从当前目录导入其他模块,也可以从$PYTHONPATH目录导入。你需要明白,模块的引用其实就是指向这个模块的相对路径。所以说,解释器无法导入在文件系统中找不到的模块。
要让foo这个文件正常工作,它的上级目录必须在Python的搜索路径里:
$ ls foo
eggs.py ham.py ham.pyc __init__.py __init__.pyc
$ python foo/ham.py
got ham!
$ python foo/eggs.py
got eggs, importing ham!
Traceback (most recent call last):
File "foo/eggs.py", line 2, in <module>
import foo.ham
ImportError: No module named foo.ham
$ PYTHONPATH=. python foo/eggs.py
got eggs, importing ham!
got ham!
这看起来是可行的:下面是目录结构:
~/test/kl% ls -R
.:
foo spam.py
./foo:
eggs.py eggs.pyc ham.py ham.pyc __init__.py __init__.pyc
这里是文件内容:
~/test/kl% cat spam.py
import foo.eggs
~/test/kl% cd foo/
~/test/kl/foo% cat eggs.py
print( "got eggs, importing ham!" )
import ham
我们可以从 spam.py 和 foo/eggs.py 中导入 ham:
~/test/kl% python spam.py
got eggs, importing ham!
got ham!
一个有用的规则是,当你输入 python script.py
时,包含 script.py
的目录会被加到 sys.path
的最前面,sys.path
是用来查找模块的目录列表。这就是为什么 python spam.py
可以正常工作,而不需要改变 PYTHONPATH
的原因。
~/test/kl% python foo/eggs.py
got eggs, importing ham!
got ham!
在这里,~/test/kl/foo 被添加到了 sys.path
中。这没问题,因为 eggs.py
试图 import ham
。由于 ham.py
在 ~/test/kl/foo
中,而这个目录在 sys.path
里,所以 Python 能顺利找到它。
~/test/kl% cd foo
~/test/kl/foo% python eggs.py
got eggs, importing ham!
got ham!
目录 ~/test/kl 并不在我的 PYTHONPATH 中。