0

我正在使用python 3.7。使用时imp,我注意到相对导入的工作方式不同,具体取决于相对导入发生的位置。

例如,我有以下目录:

.
├── __init__.py
└── dir2
    ├── __init__.py
    ├── a.py
    └── b.py

和文件内容如下:

~/personal/dir1 via  v3.7.7 via C py372
❯ cat dir2/__init__.py
from .a import default
print("default is", default)

~/personal/dir1 via  v3.7.7 via C py372
❯ cat dir2/a.py

default = 12

~/personal/dir1 via  v3.7.7 via C py372
❯ cat dir2/b.py
from .a import default
print("default is", default)

~/personal/dir1 via  v3.7.7 via C py372

imp.load_source同时使用dir2/__init__.pyand dir2/b.py,得到以下结果:

❯ ipython
Python 3.7.7 (default, May  6 2020, 04:59:01)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import imp
/Users/user/anaconda3/envs/py372/bin/ipython:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  #!/Users/user/anaconda3/envs/py372/bin/python

In [2]: imp.load_source("m", "dir2/__init__.py")
default is 12
Out[2]: <module 'm' from 'dir2/__init__.py'>

In [3]: imp.load_source("m", "dir2/b.py")
---------------------------------------------------------
ImportError             Traceback (most recent call last)
<ipython-input-3-40c4f63c0bb1> in <module>
----> 1 imp.load_source("m", "dir2/b.py")

~/anaconda3/envs/py372/lib/python3.7/imp.py in load_source(name, pathname, file)
    167     spec = util.spec_from_file_location(name, pathname, loader=loader)
    168     if name in sys.modules:
--> 169         module = _exec(spec, sys.modules[name])
    170     else:
    171         module = _load(spec)

~/anaconda3/envs/py372/lib/python3.7/importlib/_bootstrap.py in _exec(spec, module)

~/anaconda3/envs/py372/lib/python3.7/importlib/_bootstrap_external.py in exec_module(self, module)

~/anaconda3/envs/py372/lib/python3.7/importlib/_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

~/personal/dir1/dir2/b.py in <module>
----> 1 from .a import default
      2 print("default is", default)

ImportError: attempted relative import with no known parent package

为什么与其他 python 文件imp.load_source的行为不同?__init__.py

4

1 回答 1

1

相对导入不是目录遍历机制。它们用于导入它们出现的包的其他内容。

当您调用 时,Python 认为您正在imp.load_source("m", "dir2/__init__.py")尝试加载名为 whois 的m包。在这种情况下,相对导入是相对于包的,它们在目录中搜索子模块。__init__.pydir2/__init__.pymdir2

当您调用 时imp.load_source("m", "dir2/b.py"),Python 认为您正在尝试加载名为m. 没有相对导入相对于的包,在这种情况下,相对导入是没有意义的。

于 2020-06-28T01:10:24.567 回答