Importar módulo de subcarpeta


104

Quiero importar subcarpetas como módulos. Por lo tanto, cada subcarpeta contiene un __init__.py. Mi estructura de carpetas es así:

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

En mi script principal importo

from dirFoo.foofactory import FooFactory

En este archivo de fábrica incluyo los submódulos:

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

Si llamo a mi foofactory, aparece el error, que Python no puede importar los submódulos foo1 y 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

Respuestas:


136

No hay necesidad de meterse con usted PYTHONPATHo sys.pathaquí.

Para utilizar correctamente las importaciones absolutas en un paquete, debe incluir también el nombre del paquete "raíz", por ejemplo:

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

O puede utilizar importaciones relativas :

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

47
¡Una cosa para recordar! agregue __init__.pya cada subcarpeta desde la que está importando.
Aziz Alto

6
Vacío __init__.pypuede hacer el trabajo.
Cerebrou

1
¿Cuál sería la sintaxis si anteriormente Foo1estuviera en el directorio principal y uno codificara algo como from Foo1 import *. ¿Hay alguna manera de lograr el mismo efecto para que no tenga que anteponer todo con Foo1?
jxramos

1
@AzizAlto: sin su comentario, esta solución no es muy útil
Alex

21

Solo para notificar aquí. (de una abeja nueva, keviv22)

Nunca jamás, por el bien de su propio bien, nombre las carpetas o archivos con símbolos como "-" o "_". Si lo hizo, es posible que tenga algunos problemas. como el mío, digamos, aunque su comando para importar es correcto, no podrá importar con éxito los archivos deseados que están disponibles dentro de esas carpetas con nombre.

Nombres de carpetas no válidos de la siguiente manera:

  • Carpeta-clases-genéricas
  • Generic_Classes_Folder

nombres de carpeta válidos para arriba:

  • GenericClassesFolder o Genericclassesfolder o genericClassesFolder (o así sin espacios ni símbolos especiales entre las palabras)

Qué error cometí:

considere la estructura del archivo.

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

¿Qué quería hacer?

  • de testFile.py, quería importar el archivo 'targetClass.py' dentro del archivo Generic-Class-Folder para usar la función llamada "functionExecute" en el archivo 'targetClass.py'

¿Qué comando hice?

  • de 'testFile.py', escribió el comando, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Tengo errores como SyntaxError: invalid syntax

Intenté muchas búsquedas y vi muchas preguntas de stackoverflow y no pude decidir qué salió mal. Verifiqué mis archivos varias veces, usé el __init__.pyarchivo, inserté la ruta del entorno y me preocupé enormemente por lo que salió mal ...

Y después de mucho, mucho tiempo, me di cuenta de esto mientras hablaba con un amigo. Soy un poco estúpido por usar tales convenciones de nomenclatura. Nunca debería usar espacios o símbolos especiales para definir un nombre para ninguna carpeta o archivo. Entonces, esto es lo que quería transmitir. ¡Tenga un buen día!

(perdón por la publicación enorme sobre esto ... simplemente dejando ir mis frustraciones .... :) ¡Gracias!)


22
Los espacios y guiones ("-") causarían esto, pero los guiones bajos ("_") deberían funcionar bien.
cowlinator

6

Establezca su variable de entorno PYTHONPATH. Por ejemplo, como este PYTHONPATH =.: .. (para la familia * nix).

También puede agregar manualmente su directorio actual (src en su caso) a pythonpath:

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

2

Digamos que su proyecto está estructurado de esta manera:

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

En el interior run.py, puede importar los scripts uno y dos mediante:

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

Ahora, aún dentro run.py, podrás llamar a sus métodos con:

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

1

Simplemente cree un archivo ___init____.py vacío y agréguelo en la raíz, así como en todo el subdirectorio / carpeta de su aplicación de Python donde tiene otros módulos de Python.


-2

Tuve problemas incluso cuando init .py existía en la subcarpeta y todo lo que faltaba era agregar 'como' después de la importación

from folder.file import Class as Class
import folder.file as functions
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.