`from ... import`与`import .` [重复]
Posted
技术标签:
【中文标题】`from ... import`与`import .` [重复]【英文标题】:`from ... import` vs `import .` [duplicate] 【发布时间】:2012-03-15 10:02:36 【问题描述】:我想知道代码片段之间是否有任何区别
from urllib import request
和片段
import urllib.request
或者它们是否可以互换。如果它们可以互换,那是“标准”/“首选”语法(如果有的话)?
【问题讨论】:
我不是导入方面的专家,所以我不会给出答案,但是关于事情的进展如何进入sys.modules
是有区别的:看看这个answer(最后)。 (也许有人比我能解释得更好)
【参考方案1】:
这取决于您在引用导入时希望如何访问它。
from urllib import request
# access request directly.
mine = request()
import urllib.request
# used as urllib.request
mine = urllib.request()
为简单起见或避免屏蔽内置插件,您还可以在导入时自己为事物起别名:
from os import open as open_
# lets you use os.open without destroying the
# built in open() which returns file handles.
【讨论】:
我刚刚尝试了 import urllib.request 并且它根本不起作用(python 2.6.5 Ubuntu)。 您应该使用尾随下划线(而不是前导)以防止与内置插件发生冲突。 @deadly - 坏习惯 - 它会阻止 Eclipse 中的 IDE 警告有时使用前导下划线。谢谢。 @g.d.d.c:PEP 8(两次)明确指定了“单个尾随下划线”约定。如果 Eclipse 产生关于正确代码的恼人警告,那么我们的 IDE 很糟糕,而不是一个坏习惯。 @tkone 在 Python 3 中,urllib2 被移到了 urllib.request。【参考方案2】:很多人已经解释了import
与from
,所以我想尝试在幕后解释更多,真正的区别在哪里。
首先,让我解释一下基本的 import 语句的作用。
import X
导入模块
X
,并在 当前命名空间。然后你需要定义完整的模块路径到 从模块内部访问特定的属性或方法(例如:X.name
或X.attribute
)
from X import *
导入模块
X
,并创建对所有公共对象的引用 由当前命名空间中的该模块定义(即,所有 没有以_
) 或任何名称开头的名称 你提到了。或者,换句话说,在你运行了这个语句之后,你可以简单地 使用普通(非限定)名称来引用模块
X
中定义的内容。 但是X
本身没有定义,所以X.name
不起作用。如果name
已经定义,它被新版本替换。如果X
中的名称是 更改为指向其他对象,您的模块不会注意到。这使得模块中的所有名称都可以在本地命名空间中使用。
现在让我们看看当我们执行import X.Y
时会发生什么:
>>> import sys
>>> import os.path
检查sys.modules
名称为os
和os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
检查 globals()
和 locals()
命名空间字典,名称为 os
和 os.path
:
>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>
从上面的例子中,我们发现只有os
被添加到本地和全局命名空间中。
所以,我们应该可以使用os
:
>>> os
<module 'os' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
……但不是path
:
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
从locals()
命名空间中删除os
后,您将无法访问os
或os.path
,即使它们确实存在于sys.modules
中:
>>> del locals()['os']
>>> os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
现在让我们看看from
。
from
>>> import sys
>>> from os import path
检查sys.modules
名称为os
和os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
所以sys.modules
看起来和我们使用import name
导入时一样。
好的。让我们检查一下 locals()
和 globals()
命名空间字典是什么样的:
>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>
您可以使用path
访问,但不能使用os.path
:
>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
让我们从 locals() 中删除“路径”:
>>> del locals()['path']
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
最后一个使用别名的例子:
>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
并且没有定义路径:
>>> globals()['path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
使用from
的一个陷阱
当您从两个不同的模块导入相同的name
时:
>>> import sys
>>> from os import stat
>>> locals()['stat']
<built-in function stat>
>>>
>>> stat
<built-in function stat>
再次从shutil
导入统计数据:
>>>
>>> from shutil import stat
>>> locals()['stat']
<module 'stat' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>> stat
<module 'stat' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>>
最后的导入将获胜
【讨论】:
确实是这样,但对我来说,所有这些命名空间等等都让我有些困惑。所以我更喜欢只使用 import x 然后 x.what_is_necessary。以我的拙见,我认为它更具可读性,更容易避免混淆,通过这种方式,你肯定会避免名称冲突歧义和所有类似的东西......对吗? 我喜欢这个答案,因为它教如何捕鱼而不是提供鱼。 `from .导入有区别。在某些情况下,其中一种会起作用,而另一种则不会。这是一个例子:假设我们有以下结构:
foo.py
mylib\
a.py
b.py
现在,我想将b.py
导入a.py
。我想将a.py
导入到foo
。我该怎么做呢?两个声明,在a
我写:
import b
在foo.py
我写:
import mylib.a
好吧,这将在尝试运行 foo.py
时生成 ImportError
。解释器会抱怨 a.py
(import b
) 中的 import 语句说没有模块 b。那么如何解决这个问题呢?在这种情况下,将a
中的import语句更改为import mylib.b
因为a
和b
都在mylib
中,所以无法工作。这里的解决方案(或至少一种解决方案)是使用绝对导入:
from mylib import b
来源:Python: importing a module that imports a module
【讨论】:
【参考方案4】:你使用的是 Python3 中的 urllib 包。这两种形式都是可以接受的,没有一种形式的进口优于另一种形式。有时当涉及多个包目录时,您可以使用前者from x.y.z.a import s
在这个带有 urllib 包的特殊情况下,第二种方式 import urllib.request
和使用 urllib.request
是标准库统一使用它的方式。
【讨论】:
【参考方案5】:至少在 python 2.x 中你不能做到import urllib2.urlopen
你必须做from urllib2 import urlopen
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib2.urlopen
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named urlopen
>>> import urllib.request
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named request
>>>
【讨论】:
嗯,那是因为urlopen
是一个函数,对吧?这就像尝试 import os.chdir
一样——就像错误消息正确地指出,“没有名为 chdir
的模块”......因为它不是一个模块!【参考方案6】:
我对 import urllib.request 的主要抱怨是你仍然可以引用 urllib.parse,即使它没有被导入。
>>> import urllib3.request
>>> urllib3.logging
<module 'logging' from '/usr/lib/python2.7/logging/__init__.pyc'>
对我的请求也在 urllib3 下。 Python 2.7.4 ubuntu
【讨论】:
以上是关于`from ... import`与`import .` [重复]的主要内容,如果未能解决你的问题,请参考以下文章
import * as react from 'react' 与 import react from 'react' 有啥区别