给定以下目录结构:
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
模块的核心库版本。你知道吗
但是,实际的import语句仍然设法以某种方式获取空的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要再次尝试导入模块,它不应该简单地使用模块缓存中已经存在的模块吗?你知道吗
你或多或少已经找到了答案。默认情况下,python2.x将首先进行包相关的导入,这包括“隐藏”基本级别包的可能性。你知道吗
请参阅python2文档中关于Intra-package References的部分。你知道吗
指定显式相对导入的能力,以及
from __future__ import absolute_import
,实际上是在python2.5中引入的,这将在PEP 328中进一步解释。这种行为成为python3中的默认行为。新的行为(假定的绝对和显式的相对导入)在很大程度上是显式实现的,以解决您提出的问题(隐藏内置模块),尽管它还允许使用多级相对导入语法进行更大的控制(例如,对于父模块..
,对于更高级别的模块...
,等等)相关问题 更多 >
编程相关推荐