Impossibile importare * da una sottodirectory in Python [duplicato]
Sto cercando di importare un set di moduli da una sottodirectory in un singolo modulo principale nella directory principale:
Progetto/
main.py
subdirectory/
__init__.py
timer.py
example.py
Posso chiedere uno qualsiasi dei singoli file .py in questo modo:
from subdirectory import timer.py
Ma, se eseguo il seguente comando,
from subdirectory import *
e provo a utilizzare un modulo all'interno di quella sottodirectory, ottengo il seguente errore:
File "My:\Path\Here\...", line 33, in main
t = timer.timer()
NameError: name 'timer' is not defined
Voglio essere in grado di importare tutti i file in un batch, poiché sto importando un paio di moduli. Ho già aggiunto un file init .py vuoto alla sottodirectory. C'è qualcosa che mi manca?
Risposte
Devi dichiarare i nomi dei tuoi moduli usando __all__nel tuo __init__.py:
__init__.py:
__all__ = ["timer", "example"]
Questo comportamento è documentato :
L'unica soluzione è che l'autore del pacchetto fornisca un indice esplicito del pacchetto. L'
importistruzione utilizza la seguente convenzione: se il__init__.pycodice di un pacchetto definisce un elenco denominato__all__, viene considerato l'elenco dei nomi dei moduli che dovrebbero essere importati quandofrom package import *si incontra.
Se vuoi solo far funzionare le importazioni, aggiungi subdirectory/__init__.pycon il seguente contenuto:
from * import example
from * import timer
Tuttavia, se vuoi farlo su un numero arbitrario di moduli (vecchi e nuovi), penso che questa risposta potrebbe essere quello che stai cercando:
Inizi con la seguente struttura:
main.py
subdirectory/
subdirectory/__init__.py
subdirectory/example.py
subdirectory/timer.py
Quindi importa tutto subdirectoryda main.py:
from subdirectory import *
t = timer.timer()
Quindi aggiungi quanto segue al subdirectory/__init__.pymodulo:
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not
f.endswith('__init__.py')]
E per completezza il subdirectory/timer.pymodulo:
def timer():
return 42
Le importazioni vanno così.
# if you have timer.py, import it as
import timer
Prova ad aggiungere __init__.pyalla sottodirectory. Ora apparirà come:
Progetto/
main.py
subdirectory/
__init__.py
timer.py
example.py
Se non funziona: in main.pyadd
import sys
sys.path.append("path/to/subdirectory") # replace with the path
import timer