Importer le module du sous-dossier

104

Je souhaite importer des sous-dossiers en tant que modules. Par conséquent, chaque sous-dossier contient un fichier __init__.py. Ma structure de dossiers est comme ceci:

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

Dans mon script principal, j'importe

from dirFoo.foofactory import FooFactory

Dans ce fichier d'usine, j'inclus les sous-modules:

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

Si j'appelle ma foofactory, j'obtiens l'erreur, ce python ne peut pas importer les sous-modules foo1 et 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
Razer
la source

Réponses:

136

Il n'y a pas besoin de jouer avec votre PYTHONPATHou sys.pathici.

Pour utiliser correctement les importations absolues dans un paquet, vous devez également inclure le nom de paquet "racine", par exemple:

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

Ou vous pouvez utiliser des importations relatives :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2
Rob Wouters
la source
47
Une chose à retenir! ajouter __init__.pyà chaque sous-dossier à partir duquel vous importez.
Aziz Alto
6
Vide __init__.pypeut faire le travail.
cerebrou
1
Quelle serait la syntaxe si auparavant se Foo1trouvait dans le répertoire parent et que quelqu'un codait quelque chose comme from Foo1 import *. Existe-t-il un moyen d'obtenir le même effet pour ne pas avoir à tout préfixer Foo1?
jxramos
1
@AzizAlto: sans votre commentaire cette solution n'est pas très utile
Alex
21

Juste pour notifier ici. (d'un newbee, keviv22)

Jamais et jamais pour votre propre bien, nommez les dossiers ou fichiers avec des symboles comme "-" ou "_". Si vous l'avez fait, vous pourriez rencontrer quelques problèmes. comme le mien, par exemple, bien que votre commande d'importation soit correcte, vous ne pourrez pas importer avec succès les fichiers désirés qui sont disponibles dans ces dossiers nommés.

Noms de dossier non valides comme suit:

  • Dossier de classes génériques
  • Generic_Classes_Folder

noms de dossier valides pour ci-dessus:

  • GenericClassesFolder ou Genericclassesfolder ou genericClassesFolder (ou comme ça sans espaces ou symboles spéciaux parmi les mots)

Quelle erreur j'ai fait:

considérez la structure des fichiers.

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

Qu'est-ce que je voulais faire?

  • à partir de testFile.py, je voulais importer le fichier 'targetClass.py' dans le fichier Generic-Class-Folder pour utiliser la fonction nommée "functionExecute" dans le fichier 'targetClass.py'

Quelle commande j'ai fait?

  • à partir de 'testFile.py', commande écrite, from Core.Generic-Class-Folder.targetClass import functionExecute
  • J'ai des erreurs comme SyntaxError: invalid syntax

J'ai essayé de nombreuses recherches et vu de nombreuses questions de stackoverflow et j'ai été incapable de décider de ce qui n'allait pas. J'ai vérifié plusieurs fois mes fichiers, j'ai utilisé un __init__.pyfichier, un chemin d'environnement inséré et je m'inquiétais énormément de ce qui n'allait pas ......

Et après un long long moment, j'ai compris cela en parlant avec un de mes amis. Je suis un peu stupide d'utiliser de telles conventions de dénomination. Je ne devrais jamais utiliser d'espace ou de symboles spéciaux pour définir un nom pour un dossier ou un fichier. Donc, c'est ce que je voulais transmettre. Bonne journée!

(désolé pour l'énorme message à ce sujet ... laisser passer mes frustrations .... :) Merci!)

Vivek22
la source
22
Les espaces et les tirets ("-") en seraient la cause, mais les traits de soulignement ("_") devraient toujours fonctionner correctement.
cowlinator
6

Définissez votre variable d'environnement PYTHONPATH. Par exemple comme ceci PYTHONPATH =.: .. (pour la famille * nix).

Vous pouvez également ajouter manuellement votre répertoire actuel (src dans votre cas) à pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())
Max Kamenkov
la source
2

Dites que votre projet est structuré de cette façon:

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

À l'intérieur run.py, vous pouvez importer les scripts un et deux en:

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

Maintenant, toujours à l'intérieur run.py, vous pourrez appeler leurs méthodes avec:

One.method_from_one(param)
Two.method_from_two(other_param)
Flavio Wuensche
la source
1

Créez simplement un fichier ___init____.py vide et ajoutez-le à la racine ainsi que dans tous les sous-répertoires / dossiers de votre application python où vous avez d'autres modules python.

Abhijit Pritam Dutta
la source
-2

Avait des problèmes même lorsque init .py existait dans le sous-dossier et tout ce qui manquait était d'ajouter `` comme '' après l'importation

from folder.file import Class as Class
import folder.file as functions
Tomas Trdla
la source