Perché i moduli Python a volte non importano i loro sottomoduli?


91

Ho notato qualcosa di strano oggi che vorrei fosse spiegato. Non ero sicuro al 100% come formulare questa domanda come una domanda, quindi Google è fuori discussione. Il modulo logging non ha accesso al modulo logging.handlers per qualche strana ragione. Provalo tu stesso se non mi credi:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

Qualcuno può spiegare perché questo accade?

Risposte:


122

In Python, i moduli devono essere importati prima di essere accessibili. import loggingimporta solo il modulo di registrazione. Accade così che loggingsia un pacchetto con sottomoduli, ma quei sottomoduli non vengono ancora caricati automaticamente. Quindi, è necessario importare esplicitamente logging.handlersprima di potervi accedere.

Se ti stai chiedendo perché a volte sembra che tu non abbia bisogno di queste importazioni extra: alcuni pacchetti importano alcuni o tutti i loro sottomoduli quando vengono importati, semplicemente eseguendo tali importazioni nei loro __init__.pyfile. In altri casi potrebbe essere qualcos'altro che importi, anche importato logging.handlers. Non importa quale parte di codice importa; fintanto che qualcosa nel tuo processo viene importato logging.handlersprima di accedervi, sarà lì. E a volte un modulo che assomiglia a un pacchetto in realtà non lo è, come ose os.path. osnon è un pacchetto, importa solo l'altro modulo corretto (per la tua piattaforma) e lo chiama path, solo così puoi accedervi come os.path.


4

Sono anche nuovo di Python e dopo aver fatto molta pratica ora posso distinguere tra pacchetto (cartella), modulo (.py), classi, variabili ... ecc ...

se vuoi che una qualsiasi delle tue cartelle sia un pacchetto python - Deve contenere __init__.pyfile anche un file vuoto lo farà !!!

e come ha detto Thomas, puoi importare un modulo aggiuntivo in __init__.py se vuoi !!! ma i moduli / pacchetti sono accessibili solo dopo averlo importato ...

se vuoi importare tutto da un modulo puoi usare

from logging import *

resto puoi accedere anche al modulo gestori come sotto,

from logging import handlers
print dir(handlers)


5
Si prega di non utilizzare from module import *. È quasi sempre un errore.
Thomas Wouters,

Se vuoi che tutto in un pacchetto venga importato automaticamente, esegui queste importazioni in init .py, invece di impostare tutto in init .py e fare "from package import *" da qualche parte.
Thomas Wouters,

2
@Pete: perché "inquina" lo spazio dei nomi standard che porta all'ambiguità e al conflitto. Se lo avessi fatto import zippere zipper.open()tu sapresti esattamente quale open stavo chiamando. Al contrario from zipper import *seguito da open()è il built-in open o zipper.open o qualcos'altro. import zipper as zè di gran lunga preferito se ti stanchi di digitarezipper
msw

3
@Pete: è anche un problema perché potresti sovrascrivere inconsapevolmente parte del tuo spazio dei nomi. numpy import *Usavo from perché alcune funzioni numpy non funzionano a meno che non importi tutto numpy (terribile difetto di progettazione da parte loro IMO) ma numpy ha un numero ENORME di oggetti che importa. Ho finito per sovrascrivere molte funzioni (credo che la copia fosse una ... sono troppo stanco per controllare). Ora importo numpy come np se userò numpy così tanto che non sopporto di scriverlo più e più volte.
chriscauley

2
@dustynachos, quale funzione numpy ha quel difetto?
Winston Ewert

2

Thomas Wouters ha risposto molto bene a questa domanda, ma purtroppo ho trovato questa domanda solo dopo aver trovato la risposta nella documentazione originale. A tal fine ho pensato di aggiungere a questo nella speranza che si presenti più vicino alla parte superiore del motore di ricerca in futuro.

DOMANDA

Perché viene visualizzato l'errore: " AttributeError: module" module_name "non ha attributo" sub_module_name "anche se il mio editor (ad es. Visual Code) completa automaticamente il nome del sottomodulo:

 import module_name
 module_name.sub_module_name(parameter)

RISPOSTA

Il tuo editor sta basando il suo completamento automatico sulla struttura dei file del tuo progetto e non sul comportamento di Python. I sottomoduli non vengono importati "automaticamente" quando si importa un modulo. Fare riferimento alla documentazione di Python per i dettagli su come importare "automaticamente" i sottomoduli durante l'utilizzo

 import module_name

Il contributo chiave con questa risposta è l'aggiunta di AttributeError quando si tenta di importare un "modulo" o un "pacchetto"

Spero che questo aiuti qualcuno!


1

Di recente ho affrontato la stessa strana situazione. Quindi, scommetto che hai rimosso alcune importazioni di librerie di terze parti. Quella lib rimossa conteneva from logging import handlerso from logging import *e ti ha fornito handlers. E in un'altra sceneggiatura hai avuto qualcosa di simile import logginge appena usato logging.handlerse hai pensato che è un modo in cui le cose funzionano come ho fatto io.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.