【问题标题】:Python import statement semanticsPython 导入语句语义
【发布时间】:2012-10-26 20:05:05
【问题描述】:

我很难理解 import 语句及其变体。

假设我正在使用lxml 模块来抓取网站。

以下示例显示...

from lxml.html import parse
parse( 'http://somesite' )

...Google 的 python 样式指南更喜欢基本的 import 语句,以保留命名空间。

我更愿意这样做,但是当我尝试这样做时:

import lxml
lxml.html.parse( 'http://somesite' )

...然后我收到以下错误消息:

AttributeError: 'module' 对象没有属性 'html'

谁能帮我理解发生了什么?我更喜欢在它们的命名空间中使用模块,但需要一些帮助来理解语义。

【问题讨论】:

    标签: python python-import


    【解决方案1】:
    import lxml.html as LH
    doc = LH.parse('http://somesite')
    

    lxml.html 是一个模块。当您 import lxml 时,html 模块不会导入到 lxml 命名空间中。这是开发商的决定。有些包会自动导入一些模块,有些则不会。在这种情况下,您必须自己使用import lxml.html

    import lxml.html as LH 导入 html 模块并将其绑定到当前模块命名空间中的名称 LH。所以你可以使用LH.parse访问解析函数。


    如果您想深入了解包(如lxml)何时自动导入模块(如lxml.html),请打开终端并输入

    In [16]: import lxml
    
    In [17]: lxml
    Out[17]: <module 'lxml' from '/usr/lib/python2.7/dist-packages/lxml/__init__.pyc'>
    

    这是lxml 包的__init__.py 文件的路径。 如果您查看内容,您会发现它是空的。所以没有子模块被导入。如果你查看 numpy 的 __init__.py,你会看到很多代码,其中有

    import linalg
    import fft
    import polynomial
    import random
    import ctypeslib
    import ma
    

    这些都是导入numpy命名空间的子模块。因此,从用户的角度来看,import numpy 会自动为您提供对numpy.linalgnumpy.fft 等的访问权限。

    【讨论】:

    • 我应该将 lxml 视为一个包吗?是否有任何一致的方法可以确定哪些模块会自动加载到我的程序中?
    • @TravisLelue:在 Python 中,包含 __init__.py 的目录是一个包。因此,lxml 是一个包。模块是包内的任何.py 文件。我的编辑(希望)解释了如何找出哪些模块会自动导入到包的命名空间中。
    • 目录结构中的所有子模块和子包一旦被导入,将在其父包的命名空间中可用,无论它们是否在包的__init__.py 中导入。 __init__.py 仅使得其中的任何 imported 在导入包后自动可用,并且通过__init__.py 中使用的from x.y import z 表单允许开发人员将包目录层次结构与包命名空间布局分离.
    【解决方案2】:

    我们以包pkg 为例,其中包含两个模块a.pyb.py

    --pkg
       |
       | -- a.py
       |
       | -- b.py
       |
       | -- __init__.py
    

    __init__.py 中,您正在导入a.py不是 b.py

    导入一个

    因此,如果您打开终端并执行以下操作:

    >>> import pkg
    >>> pkg.a
    >>> pkg.b
    AttributeError: 'module' object has no attribute 'b'
    

    正如你所看到的,因为我们在 pkg 的 __init__.py 中导入了 a.py,我们可以将它作为 pkg 的属性访问,但 b 不存在,所以稍后要访问它,我们应该使用:

    >>> import pkg.b   # OR: from pkg import b
    

    HTH,

    【讨论】:

      【解决方案3】:

      当您import 一个包时,解释器在 pythonpath 上查找该包,如果找到,解析并运行包的__init__.py,从中构建一个包对象,并将该对象插入到sys.modules .当importing 一个模块时,它做同样的事情,除了它创建和添加一个模块对象。当您随后尝试访问属性(也称为成员方法、类、子模块或子包)时,它会从 sys.modules 检索相应的对象,并尝试在模块或包对象上为您想要的子对象创建 getattr。但是,如果子模块或子包尚未成为imported,则它尚未添加到sys.modules 或模块或包的属性列表中,因此您将获得AttributeError。因此,您必须在代码中显式导入模块或包,或者在包的 __init__.py 中委派,以便在运行时在其父级上可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-04
        • 2022-10-13
        • 2023-02-15
        • 2018-09-21
        • 1970-01-01
        • 2010-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多