Importa modulo dalla sottocartella


104

Voglio importare le sottocartelle come moduli. Pertanto ogni sottocartella contiene un file __init__.py. La mia struttura di cartelle è così:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

Nel mio script principale importo

from dirFoo.foofactory import FooFactory

In questo file di fabbrica includo i sottomoduli:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

Se chiamo il mio foofactory ottengo l'errore, quel python non può importare i sottomoduli foo1 e foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1

Risposte:


136

Non c'è bisogno di scherzare con il tuo PYTHONPATHo sys.pathqui.

Per usare correttamente le importazioni assolute in un pacchetto dovresti includere anche il nome del pacchetto "root", ad esempio:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Oppure puoi usare le importazioni relative :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2

47
Una cosa da ricordare! aggiungi __init__.pya ogni sottocartella da cui stai importando.
Aziz Alto

6
Vuoto __init__.pypuò fare il lavoro.
cerebrou

1
Quale sarebbe la sintassi se in precedenza si Foo1trovava nella directory principale e una codificava qualcosa di simile from Foo1 import *. C'è un modo per ottenere lo stesso effetto in modo da non dover anteporre a tutto Foo1?
jxramos

1
@AzizAlto: senza il tuo commento questa soluzione non è molto utile
Alex

21

Solo per notificare qui. (da un novellino, keviv22)

Mai e poi mai per il tuo bene, dai un nome alle cartelle o ai file con simboli come "-" o "_". In tal caso, potresti riscontrare alcuni problemi. come il mio, diciamo, sebbene il tuo comando per l'importazione sia corretto, non sarai in grado di importare con successo i file desiderati che sono disponibili all'interno di tali cartelle denominate.

Nomi di cartelle non validi come segue:

  • Generic-classi-Folder
  • Generic_Classes_Folder

nomi di cartella validi per sopra:

  • GenericClassesFolder o Genericclassesfolder o genericClassesFolder (o così senza spazi o simboli speciali tra le parole)

Che errore ho fatto:

considera la struttura del file.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

Cosa volevo fare?

  • da testFile.py, volevo importare il file 'targetClass.py' all'interno del file Generic-Class-Folder per utilizzare la funzione denominata "functionExecute" nel file 'targetClass.py'

Che comando ho fatto?

  • da 'testFile.py', ha scritto il comando, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Hai errori come SyntaxError: invalid syntax

Ho provato molte ricerche e visualizzato molte domande su stackoverflow e non sono riuscito a decidere cosa è andato storto. Ho controllato i miei file più volte, ho usato il __init__.pyfile, inserito il percorso dell'ambiente e sono estremamente preoccupato per cosa è andato storto ...

E dopo tanto tempo, l'ho capito parlando con un mio amico. Sono un po 'stupido ad usare tali convenzioni di denominazione. Non dovrei mai usare spazi o simboli speciali per definire un nome per qualsiasi cartella o file. Quindi, questo è ciò che volevo trasmettere. Buona giornata!

(scusa per l'enorme post su questo ... lasciando andare le mie frustrazioni ... :) Grazie!)


22
Spazi e trattini ("-") causerebbero ciò, ma i trattini bassi ("_") dovrebbero comunque funzionare correttamente.
cowlinator

6

Imposta la tua variabile d'ambiente PYTHONPATH. Ad esempio come questo PYTHONPATH =.: .. (per la famiglia * nix).

Inoltre puoi aggiungere manualmente la tua directory corrente (src nel tuo caso) a pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())

2

Supponi che il tuo progetto sia strutturato in questo modo:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

All'interno run.py, puoi importare gli script uno e due:

from subscripts import script_one as One
from subscripts import script_two as Two

Ora, sempre all'interno run.py, potrai chiamare i loro metodi con:

One.method_from_one(param)
Two.method_from_two(other_param)

1

Basta creare un file ___init____.py vuoto e aggiungerlo nella root così come in tutte le sottodirectory / cartelle della tua applicazione python in cui hai altri moduli python.


-2

Ha avuto problemi anche quando init .py esisteva nella sottocartella e mancava solo l'aggiunta di "as" dopo l'importazione

from folder.file import Class as Class
import folder.file as functions
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.