Семантика оператора импорта Python

У меня возникают трудности с пониманием оператора импорта и его вариантов.

Предположим, я используюlxml модуль для соскоба сайтов.

Следующие примеры показывают ...

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

... Руководство по стилю Google Python предпочитает базовый оператор импорта, чтобы сохранить пространства имен.

Я бы предпочел сделать это, но когда я попробую это:

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

... тогда я получаю следующее сообщение об ошибке:

AttributeError: у объекта 'module' нет атрибута 'html'

Может ли кто-нибудь помочь мне понять, что происходит? Я бы предпочел использовать модули в их пространствах имен, но мне нужна помощь в понимании семантики.

Ответы на вопрос(3)

import пакет, интерпретатор ищет пакет в pythonpath, затем, если найден, анализирует и запускает пакет__init__.pyстроит из него объект пакета и вставляет этот объект вsys.modules, когдаimporting модуль, он делает то же самое, за исключением того, что создает и добавляет объект модуля. Когда вы впоследствии пытаетесь получить доступ к атрибуту (такому как метод-член, класс, субмодуль или подпакет), он извлекает соответствующий объект изsys.modules и пытаетсяgetattr на модуле или объекте пакета для ребенка, которого вы хотите. Однако, если ребенок является субмодулем или подпакетом, который еще не былimported, он не был добавлен кsys.modules или список атрибутов модуля или пакета, так что вы получитеAttributeError, Таким образом, вы должны явно импортировать модуль или пакет, либо в вашем коде, либо делегировать в пакете__init__.py для того, чтобы это было доступно во время выполнения на его родителе.

Решение Вопроса
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's__init__.pyВы видите много кода, среди которых

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

Это все подмодули, которые импортируются вnumpy Пространство имен. Так что с точки зрения пользователя,import numpy автоматически дает вам доступ кnumpy.linalg, numpy.fft, и т.д.

 Silas Ray26 окт. 2012 г., 22:26
Все субмодули и подпакеты в структуре каталогов будут доступны в пространстве имен их родительского пакета после их импорта независимо от того, импортированы ли они в__init__.py за пакет или нет.__init__.py только делает так, чтобы что-нибудьimported в нем автоматически доступен, как только пакет импортируется, и черезfrom x.y import z форма используется в__init__.py позволяет разработчику отделить иерархию каталогов пакета от макета пространства имен пакета.
 Travis Leleu26 окт. 2012 г., 22:13
Должен ли я думать о lxml как о пакете? Есть ли последовательный способ выяснить, какие модули автоматически загружаются в мою программу?
 unutbu26 окт. 2012 г., 22:22
@TravisLelue: в Python каталог, который содержит__init__.py это пакет. Таким образом,lxml это пакет. Модуль любой.py файл внутри пакета. Моя редакция (надеюсь) объясняет, как вы можете узнать, какие модули автоматически импортируются в пространство имен пакета.
 Robert Smith26 окт. 2012 г., 22:09
Но объясните, почему это работает.

Давайте возьмем пример пакетаpkg с двумя модулямиa.py а такжеb.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'

Как вы можете видеть, потому что мы импортировалиa.py в пкг__init__.pyмы смогли получить к нему доступ как к атрибутуpkg ноb не существует, поэтому для доступа к этому позже мы должны использовать:

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

НТН,

Ваш ответ на вопрос