`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】:

很多人已经解释了importfrom,所以我想尝试在幕后解释更多,真正的区别在哪里。

首先,让我解释一下基本的 import 语句的作用。

import X

导入模块X,并在 当前命名空间。然后你需要定义完整的模块路径到 从模块内部访问特定的属性或方法(例如: X.nameX.attribute)

from X import *

导入模块X,并创建对所有公共对象的引用 由当前命名空间中的该模块定义(即,所有 没有以_) 或任何名称开头的名称 你提到了。

或者,换句话说,在你运行了这个语句之后,你可以简单地 使用普通(非限定)名称来引用模块X 中定义的内容。 但是X 本身没有定义,所以X.name 不起作用。如果name 已经定义,它被新版本替换。如果X 中的名称是 更改为指向其他对象,您的模块不会注意到。

这使得模块中的所有名称都可以在本地命名空间中使用。

现在让我们看看当我们执行import X.Y 时会发生什么:

>>> import sys
>>> import os.path

检查sys.modules 名称为osos.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() 命名空间字典,名称为 osos.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 后,您将无法访问osos.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 名称为osos.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 .导入 ' 是什么意思?不知道圆点指的是什么。 点表示它是相对导入,一个表示当前目录,两个表示父目录,依此类推。【参考方案3】:

有区别。在某些情况下,其中一种会起作用,而另一种则不会。这是一个例子:假设我们有以下结构:

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 因为ab 都在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 .` [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python的from import和import的区别

import * as react from 'react' 与 import react from 'react' 有啥区别

python import 与 from .... import ...区别

import与from....import...区别

Python import与from import使用

Python的from import和import的区别