今天在看 Python cookbook
https://python3-cookbook.readthedocs.io/zh_CN/latest/c10/p03_import_submodules_by_relative_names.html
看到了相对导入。
相对导入的格式如下:
from . import a
from .. import a
from ..b import b
‘.’指的是当前文件夹,’..’指的是上一级文件夹, ‘..b’则是’../b’,即上一级文件夹中的b
举一个例子,文件结构如下图所示
a1.py中有三个相对导入
print 'a1'
from . import a2
from ..b import b
from .. import c
_ _main _ _.py的代码为
import a.a1
这时候如果直接运行python test,会出现以下错误
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/home/echo/test/__main__.py", line 2, in <module>
import a.a1
File "test/a/a1.py", line 3, in <module>
from ..b import b
ValueError: Attempted relative import beyond toplevel package
很奇怪,明明是在最外层运行的程序,怎么会说beyond toplevel package。
但是,如果直接在python shell中import test.__main_
_
是成功的,输出为:
a1
a2
b
c
我们把a1.py的代码改一下就能明白了问题所在了
print 'name is', __name__
#print 'a1'
#from . import a2
#from ..b import b
#from .. import c
如果在python shell中import test.__main__
,结果为
name is test.a.a1
直接运行python test得到的结果是
name is a.a1
看出问题所在了,在第二种情况下import a.a1时,它认为没有在最外层。
Python中有一个python -m xxx.py的指令,对我们的程序用python -m test,是成功的。
python -m 是将py文件当做模块来启动。
所以,我们最好将用到了相对导入的地方作为一个模块,被程序入口import。
如果我们在最外面新建一个run.py,内容为
import test.__main__
这时,程序就可以正常运行。(当然,最好重命名下_ _ main _ _.py)