2012-10-26 8 views
14

Sono un novizio pitone e sto avendo difficoltà a comprendere l'istruzione import e le sue varianti.semantica di importazione python semantica

Supponiamo che io stia usando il modulo lxml per raschiare i siti web.

Gli esempi mostrano,

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

guida di stile pitone di Google preferisce la dichiarazione di importazione di base, per preservare gli spazi dei nomi. Preferirei farlo, ma quando provo:

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

ottengo il seguente messaggio di errore:

AttributeError: 'module' object has no attribute 'html'

Qualcuno può aiutarmi a capire cosa sta succedendo? Preferisco di gran lunga usare i moduli w/nei loro spazi dei nomi, ma ho bisogno di assistenza per capire la semantica.

Molto apprezzato.

risposta

9
import lxml.html as LH 
doc = LH.parse('http://somesite') 

lxml.html è un modulo. Quando si import lxml, il modulo html non viene importato nello spazio dei nomi lxml. Questa è una decisione dello sviluppatore. Alcuni pacchetti importano automaticamente alcuni moduli, altri no. In questo caso, devi farlo da solo con import lxml.html.

import lxml.html as LH importa il modulo html e lo associa al nome LH nello spazio dei nomi del modulo corrente. Quindi è possibile accedere alla funzione di analisi con LH.parse.


Se si vuole approfondire quando un pacchetto (come lxml) importa moduli (come lxml.html) automaticamente, aprire un terminale e digitare

In [16]: import lxml 

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

Qui è si vede il percorso del lxml pacchetto __init__.py file. Se guardi il contenuto, trovi che è vuoto. Quindi nessun sottomodulo viene importato. Se si guarda in NumPy di ​​__init__.py, si vede un sacco di codice, tra i quali è

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

Questi sono tutti i moduli che sono importati nella numpy namespace. Quindi, dal punto di vista di un utente, import numpy dà automaticamente accesso al numpy.linalg, numpy.fft, ecc

+2

Ma spiegate perché funziona. –

+0

Dovrei pensare a lxml come pacchetto, quindi? C'è un modo coerente per capire quali moduli vengono caricati automaticamente nel mio programma? –

+0

@TravisLelue: In Python una directory che contiene un '__init __. Py' è un pacchetto. Pertanto, 'lxml' è un pacchetto. Un modulo è qualsiasi file '.py' all'interno di un pacchetto. La mia modifica (si spera) spiega come puoi scoprire quali moduli vengono automaticamente importati nello spazio dei nomi di un pacchetto. – unutbu

3

Quando si import un pacchetto, l'interprete cerca il pacchetto sul PYTHONPATH, poi se trovato, analizza e gestisce il __init__.py pacchetto, edificio un oggetto pacchetto da esso e inserisce quell'oggetto in sys.modules. Quando il modulo importing fa la stessa cosa, eccetto che crea e aggiunge un oggetto modulo. Quando si tenta successivamente di accedere a un attributo (noto anche come metodo membro, classe, sottomodulo o sotto pacchetto), recupera l'oggetto corrispondente da sys.modules e tenta un getattr sul modulo o sull'oggetto pacchetto per il figlio desiderato. Tuttavia, se il bambino è un sottomodulo o un sotto pacchetto che non è ancora stato imported, non è stato aggiunto a sys.modules o all'elenco di attributi del modulo o del pacchetto, quindi si ottiene AttributeError.Pertanto, devi importare esplicitamente un modulo o un pacchetto, nel tuo codice, o delegato nel pacchetto __init__.py affinché sia ​​disponibile in runtime sul suo genitore.

6

Facciamo un esempio di un pacchetto pkg con due moduli in esso a.py e b.py:

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

in __init__.py si sta importando a.py e nonb.py:

import a

Quindi, se si apri il terminale e fai:

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

Come si può vedere perché abbiamo importato a.py in pkg di __init__.py, c'è stato in grado di accedervi come un attributo di pkg ma b non c'è, per così accedere a questo poi dovremmo usare:

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

HTH,