import语句是如何找到该模块的?

2024-04-19 18:13:27 发布

您现在位置:Python中文网/ 问答频道 /正文

给定以下目录结构:

here/
├── app
│   ├── __init__.py
│   ├── json.py
│   └── example.py
└── my_script.py

__init__.pyjson.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要再次尝试导入模块,它不应该简单地使用模块缓存中已经存在的模块吗?你知道吗


Tags: 模块文件pathfrompyimportjsonapp
1条回答
网友
1楼 · 发布于 2024-04-19 18:13:27

你或多或少已经找到了答案。默认情况下,python2.x将首先进行包相关的导入,这包括“隐藏”基本级别包的可能性。你知道吗

请参阅python2文档中关于Intra-package References的部分。你知道吗

指定显式相对导入的能力,以及from __future__ import absolute_import,实际上是在python2.5中引入的,这将在PEP 328中进一步解释。这种行为成为python3中的默认行为。新的行为(假定的绝对和显式的相对导入)在很大程度上是显式实现的,以解决您提出的问题(隐藏内置模块),尽管它还允许使用多级相对导入语法进行更大的控制(例如,对于父模块..,对于更高级别的模块...,等等)

相关问题 更多 >