'import x' 和 " 'from x import y' 和 'import x.y' " 的区别

3

我尝试过

from urllib import request 
mine = request.Request()

并且

import urllib.request
mine = urllib.request.Request()

他们都能正常工作。但是…
import urllib
mine = urllib.request.Request()

提供给我

AttributeError: 'module' object has no attribute 'request' 

考虑到request是urllib的属性,为什么不会起作用呢?如果确实如此,为什么之前的语句可以正常工作呢?我使用的是Python 3.4.3。


1
当运行前两个代码片段时,我会收到“'module' object is not callable”错误。我不会说它们工作“良好”。 - vaultah
3
为什么你把模块当成函数来调用? - illright
请查看urllib文件夹。 - Padraic Cunningham
1
@Nithinjt,我猜测urllib.request()应该是urllib.request.Request(),你应该编辑你的问题。 - Padraic Cunningham
是的,你说得对。谢谢你指出来。 - Maaverik
1个回答

4

Python在导入包时,并不会导入该包内所有的内容,而是只会导入该包的__init__.py文件中的内容。(至少看起来是这样的。)

我进行了一些测试,得出以下结论:

>>> import urllib
>>> dir(urllib)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

如您所见,requesterrorparseresponserobotparser都不在其中。 它只导入了__init__.py文件。

因此,为了进一步测试,我查看了tkinter

以下是tkinter的文件夹: tkinter's Folder

因此,为了测试仅初始可访问__init__.py的理论,这里有一些有关于tkinter的命令:

>>> import tkinter
>>> tkinter.font
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'tkinter' has no attribute 'font'
>>> tkinter.test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'tkinter' has no attribute 'test'
>>> tkinter.test.support
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'tkinter' has no attribute 'test'
>>> dir(tkinter)
['ACTIVE', 'ALL', 'ANCHOR', 'ARC', 'BASELINE', 'BEVEL', 'BOTH', 'BOTTOM', 'BROWSE', 'BUTT', 'BaseWidget', 'BitmapImage', 'BooleanVar', 'Button', 'CASCADE', 'CENTER', 'CHAR', 'CHECKBUTTON', 'CHORD', 'COMMAND', 'CURRENT', 'CallWrapper', 'Canvas', 'Checkbutton', 'DISABLED', 'DOTBOX', 'DoubleVar', 'E', 'END', 'EW', 'EXCEPTION', 'EXTENDED', 'Entry', 'Event', 'FALSE', 'FIRST', 'FLAT', 'Frame', 'GROOVE', 'Grid', 'HIDDEN', 'HORIZONTAL', 'INSERT', 'INSIDE', 'Image', 'IntVar', 'LAST', 'LEFT', 'Label', 'LabelFrame', 'Listbox', 'MITER', 'MOVETO', 'MULTIPLE', 'Menu', 'Menubutton', 'Message', 'Misc', 'N', 'NE', 'NO', 'NONE', 'NORMAL', 'NS', 'NSEW', 'NUMERIC', 'NW', 'NoDefaultRoot', 'OFF', 'ON', 'OUTSIDE', 'OptionMenu', 'PAGES', 'PIESLICE', 'PROJECTING', 'Pack', 'PanedWindow', 'PhotoImage', 'Place', 'RADIOBUTTON', 'RAISED', 'READABLE', 'RIDGE', 'RIGHT', 'ROUND', 'Radiobutton', 'S', 'SCROLL', 'SE', 'SEL', 'SEL_FIRST', 'SEL_LAST', 'SEPARATOR', 'SINGLE', 'SOLID', 'SUNKEN', 'SW', 'Scale', 'Scrollbar', 'Spinbox', 'StringVar', 'TOP', 'TRUE', 'Tcl', 'TclError', 'TclVersion', 'Text', 'Tk', 'TkVersion', 'Toplevel', 'UNDERLINE', 'UNITS', 'VERTICAL', 'Variable', 'W', 'WORD', 'WRITABLE', 'Widget', 'Wm', 'X', 'XView', 'Y', 'YES', 'YView', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_cnfmerge', '_default_root', '_exit', '_flatten', '_join', '_magic_re', '_setit', '_space_re', '_splitdict', '_stringify', '_support_default_root', '_test', '_tkerror', '_tkinter', '_varnum', 'constants', 'getboolean', 'getdouble', 'getint', 'image_names', 'image_types', 'mainloop', 're', 'sys', 'wantobjects']

注意到在`dir`响应中出现了`mainloop`,我检查了`__init__.py`——果然,在那里定义了`mainloop()`。
因此,回答你的问题,当你执行`import urllib`时,Python只会加载`urllib`的`__init__.py`文件——而不是`request.py`。
另外一点需要注意的是,在`dir(tkinter)`中,有些变量是在`tkinter.constants`中定义的,而不是在`__init__.py`中定义的。这是因为在`tkinter`的`__init__.py`中,它使用`from tkinter.constants import *`导入了`tkinter.constants`。

非常感谢!我曾尝试过学习Python,但这是阻碍我前进的事情之一。直到现在我都找不到任何解释,现在我又想重拾Python了。 - Leon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接