导入语句是如何找到那个模块的?
How did the import statement find that module?
给定以下目录结构:
here/
├── app
│ ├── __init__.py
│ ├── json.py
│ └── example.py
└── my_script.py
__init__.py
和 json.py
是空文件。
my_script.py
的内容:
from app import example
example.py
的内容
import importlib, imp, sys, os
# ensures '' is not in sys.path
sys.path = [p for p in sys.path if p]
# ensures PYTHONPATH, if any, is not over-reaching
os.environ.pop('PYTHONPATH', None)
# ensures we do not see json.py in the cwd
assert not os.path.isfile('json.py')
print '1: ', imp.find_module('json')
print '2: ', __import__('json')
print '3: ', importlib.import_module('json')
import json
json.loads
现在,从 here
目录,执行:
python ./my_script.py
你会看到方法1、2、3,都找到了json
模块的核心库版本。
然而,实际的导入语句仍然设法以某种方式获取空的 json.py
文件 (AttributeError: 'module' object has no attribute 'loads'
)。
我的理解是json这里的包版本应该只能通过命名空间访问,即from app import json
,但命名空间在这里似乎不起作用。
在 python3,我无法重现该问题。我还注意到,如果我们将 from __future__ import absolute_import
放入 example.py
文件中,问题就会消失。
import语句如何找到本地文件,为什么会隐藏核心库版本?
编辑: 另外一点,当我们到达行 import json
时,已经有一个 json 模块加载到 sys.modules
从上面的行。那么为什么 python 再次尝试导入模块,难道不应该简单地使用模块缓存中已有的模块吗?
到这里你已经差不多找到答案了。 Python 2.x 默认情况下会先进行包相关导入,其中包括 "shadowing" 基础包的潜力。
请参阅 python 2 文档中有关 Intra-package References 的部分。
在 Python 2.5 中实际上引入了指定显式相对导入的能力以及 from __future__ import absolute_import
,这在 PEP 328 中有进一步解释。此行为成为 Python 中的默认行为 3. 新行为(假定绝对和显式相对导入)在很大程度上是明确实现的,以解决您提出的问题(隐藏内置模块),尽管它也允许更好地控制多级别相对导入语法(即 ..
用于父模块,...
用于更高级别,依此类推。)
给定以下目录结构:
here/
├── app
│ ├── __init__.py
│ ├── json.py
│ └── example.py
└── my_script.py
__init__.py
和 json.py
是空文件。
my_script.py
的内容:
from app import example
example.py
import importlib, imp, sys, os
# ensures '' is not in sys.path
sys.path = [p for p in sys.path if p]
# ensures PYTHONPATH, if any, is not over-reaching
os.environ.pop('PYTHONPATH', None)
# ensures we do not see json.py in the cwd
assert not os.path.isfile('json.py')
print '1: ', imp.find_module('json')
print '2: ', __import__('json')
print '3: ', importlib.import_module('json')
import json
json.loads
现在,从 here
目录,执行:
python ./my_script.py
你会看到方法1、2、3,都找到了json
模块的核心库版本。
然而,实际的导入语句仍然设法以某种方式获取空的 json.py
文件 (AttributeError: 'module' object has no attribute 'loads'
)。
我的理解是json这里的包版本应该只能通过命名空间访问,即from app import json
,但命名空间在这里似乎不起作用。
在 python3,我无法重现该问题。我还注意到,如果我们将 from __future__ import absolute_import
放入 example.py
文件中,问题就会消失。
import语句如何找到本地文件,为什么会隐藏核心库版本?
编辑: 另外一点,当我们到达行 import json
时,已经有一个 json 模块加载到 sys.modules
从上面的行。那么为什么 python 再次尝试导入模块,难道不应该简单地使用模块缓存中已有的模块吗?
到这里你已经差不多找到答案了。 Python 2.x 默认情况下会先进行包相关导入,其中包括 "shadowing" 基础包的潜力。
请参阅 python 2 文档中有关 Intra-package References 的部分。
在 Python 2.5 中实际上引入了指定显式相对导入的能力以及 from __future__ import absolute_import
,这在 PEP 328 中有进一步解释。此行为成为 Python 中的默认行为 3. 新行为(假定绝对和显式相对导入)在很大程度上是明确实现的,以解决您提出的问题(隐藏内置模块),尽管它也允许更好地控制多级别相对导入语法(即 ..
用于父模块,...
用于更高级别,依此类推。)