在Python中导入模块是否在本地范围内执行所有模块的导入?

时间:2017-11-23 16:17:13

标签: python python-import

$ python -c 'import urllib.parse; print(urllib.error.HTTPError)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: module 'urllib' has no attribute 'error'

这是预期的。我没有导入urllib.error模块。

$ python -c 'import urllib.request; print(urllib.request.HTTPError)'
<class 'urllib.error.HTTPError'>

这也是。 urllib.request imports urllib.error

from urllib.error import URLError, HTTPError, ContentTooShortError

因此名称可通过urllib.request获得。

$ python -c 'import urllib.request; print(urllib.error.HTTPError)'
<class 'urllib.error.HTTPError'>

但不是这个。是什么让我能够通过HTTPError访问urllib.error?我看过the docs,但没有看到任何线索。

2 个答案:

答案 0 :(得分:1)

好的,让我们看看:

import urllib.parse
globals()

您将看到一个项目:

'urllib': <module 'urllib' from 'C:\\Users\\XXXX\\AppData\\Local\\Programs\\Python\\Python35\\lib\\urllib\\__init__.py'>

然后,尝试dir(urllib),您会看到:

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'parse']

parse中有一个urllib,但不是requesterror。因为parse不会导入它们。

现在我们转到urllib.request

import urllib.request
globals()

获取项目:

'urllib': <module 'urllib' from 'C:\\Users\\XXXX\\AppData\\Local\\Programs\\Python\\Python35\\lib\\urllib\\__init__.py'>

import urllib.parse相同。

然后再次尝试dir(urllib)

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'error', 'parse', 'request', 'response']

其中有'error', 'parse', 'request', 'response'个。为什么? urllib.request导入

让我试着更详细地解释一下。导入urllib.request首先导入urllib,然后导入urllib.request。导入urllib会在本地范围内提供urllib符号,表示已导入的模块。导入urllib.request导入urllib.error等。这会将error符号添加到urllib模块。 ,因为我们引用了urllib ,这使我们能够在导​​入urllib.error后访问urllib.request。请考虑以下示例:

./main.py

#!/usr/bin/env python
import a.b
print(a.c.c)   # 2
print(d.e.e)   # NameError

./a/b.py

import a.c
import d.e
b = 1

./a/c.py

c = 2

./d/e.py

e = 3

答案 1 :(得分:0)

不确定它是否符合您的预期,但这是设计。你看看urllib / parse.py和urllib / request.py的来源你会看到一个重要的区别:前者只导入re,sys和collections模块,后者(除了其他不相关的模块外)也明确导入来自urllib.error,urllib.parse和urllib.response的符号。

这就是为什么即使导入不在您自己的源文件中也能找到它们的原因。

更详细的答案需要详细描述Python导入机制,远远超出SO答案中的适当范围。请参阅官方文档以获得更深入的解释。