Impossibile importare * da una sottodirectory in Python [duplicato]

Oct 26 2020

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

3 Selcuk Oct 26 2020 at 06:42

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 quando from package import *si incontra.

2 AndréC.Andersen Oct 26 2020 at 06:48

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
Deep_Thoughts Oct 26 2020 at 06:34

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