首页 文章

`from ... import` vs`import . `[复制]

提问于
浏览
199

这个问题在这里已有答案:

我想知道代码片段之间是否有任何区别

from urllib import request

和片段

import urllib.request

或者它们是否可以互换 . 如果它们是可互换的,那就是“标准”/“首选”语法(如果有的话)?

谢谢!

7 回答

  • 1

    功能上几乎没有什么区别,但第一种形式是优先的,正如你所做的那样

    from urllib import request, parse, error
    

    必须是第二种形式的地方

    import urllib.request, urllib.parse, urllib.error
    

    并且你必须使用完全限定的名称来引用,这不那么优雅 .

  • 29

    这取决于您在引用时如何访问导入 .

    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.
    
  • 3

    很多人已经解释过 import vs from ,所以我想尝试更多地解释一下实际差异所在 .

    首先,让我准确解释一下基本的import语句 .

    导入X.

    导入模块X,并在当前命名空间中创建对该模块的引用 . 然后,您需要定义已完成的模块路径以从模块内部访问特定属性或方法(例如:X.name或X.attribute)

    X导入

    *

    导入模块X,并创建对当前命名空间中该模块定义的所有公共对象的引用(即,所有没有以_开头的名称)或您提到的任何名称 . 或者,换句话说,在运行此语句之后,您可以简单地使用普通(非限定)名称来引用模块X中定义的内容 . 但是X本身未定义,因此X.name不起作用 . 如果已经定义了名称,则它将被新版本替换 . 如果X中的名称更改为指向其他对象,则模块将不会注意到 . 这使得模块中的所有名称都可在本地名称空间中使用 .

    现在让我们看看当我们做_665968时会发生什么:

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

    检查名称为 osos.pathsys.modules

    >>> 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'>
    

    检查名称为 osos.pathglobals()locals() 命名空间dict:

    >>> 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 .

    来自

    >>> import sys
    >>> from os import path
    

    检查名称为 osos.pathsys.modules

    >>> 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()中删除'path':

    >>> 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'
    >>>
    

    关于使用的一个陷阱

    当您从两个不同的模块导入相同的 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'>
    >>>
    

    THE LAST IMPORT WILL WIN

  • 0

    它们是有区别的 . 在某些情况下,其中一个将起作用,另一个则不起作用 . 这是一个例子:说我们有以下结构:

    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.pyimport b )中的进口声明说没有模块b . 那怎么能解决这个问题呢?在这种情况下,将 a 中的import语句更改为 import mylib.b 将不起作用,因为 ab 都在 mylib 中 . 这里的解决方案(或至少一个解决方案)是使用绝对导入:

    from mylib import b
    

    资料来源:Python: importing a module that imports a module

  • 186

    你正在使用Python3包中的urllib . 两种形式都是可以接受的,没有一种形式的进口优先于另一种形式 . 有时当涉及多个包目录时,您可以使用前者 from x.y.z.a import s

    在这个特殊情况下使用urllib包,第二种方式 import urllib.requesturllib.request 的使用是标准库统一使用它的方式 .

  • 15

    在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
    >>>
    
  • 135

    我对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

相关问题