¿Cómo corregir el error "ImportError: No module named ..." en Python?

115

¿Cuál es la forma correcta de corregir este error ImportError?

Tengo la siguiente estructura de directorio:

/home/bodacydo
/home/bodacydo/work
/home/bodacydo/work/project
/home/bodacydo/work/project/programs
/home/bodacydo/work/project/foo

Y estoy en el directorio

/home/bodacydo/work/project

Ahora si escribo

python ./programs/my_python_program.py

Instantáneamente consigo

ImportError: No module named foo.tasks

El ./programs/my_python_program.pycontiene la siguiente línea:

from foo.tasks import my_function

No puedo entender por qué Python no encuentra ./foo/tasks.py, está ahí.

Si lo hago desde el shell de Python, entonces funciona:

python
>>> from foo.tasks import my_function

Solo no funciona si lo llamo a través de un python ./programs/my_python_program.pyscript.

bodacydo
fuente

Respuestas:

121

Python no agrega el directorio actual sys.path, sino el directorio en el que se encuentra el script. Agregue /home/bodacydo/work/projecta sys.patho $PYTHONPATH.

Ignacio Vázquez-Abrams
fuente
9
Entonces, ¿cuál es el punto de tener init .py en la carpeta raíz? Parece que no tiene ningún propósito si edita sys.path o pythonpath.
11
@Editor: __init__.pysolo indica que el directorio debe tratarse como un paquete, cuando su padre está dentro sys.patho es en sí mismo un paquete.
Ignacio Vazquez-Abrams
3
Además, verifique los permisos en la carpeta. Ese fue el problema en mi caso.
SidJ
15
Para agregar el directorio actual a la ruta de Python, useexport PYTHONPATH=`pwd`
rodorgas
1
Lo que funcionó para mí fue agregar a $ PYTHONPATH el directorio principal del proyecto, en su caso será: /home/bodacydo/work... vea esta respuesta
maledr53
33

¿Tiene un archivo llamado __init__.pyen el directorio foo? Si no es así, Python no reconocerá a foo como un paquete de Python.

Consulte la sección sobre paquetes en el tutorial de Python para obtener más información.

Dave Kirby
fuente
Gracias y sí, lo hice __init__.py. El problema esta vez fue con $PYTHONPATH. La solución de Ignacio funcionó.
bodacydo
1
Los archivos init .py son necesarios para que Python trate los directorios como si fueran paquetes; esto se hace para evitar que los directorios con un nombre común, como cadena, oculten involuntariamente módulos válidos que aparecen más adelante en la ruta de búsqueda del módulo. En el caso más simple, init .py puede ser simplemente un archivo vacío
panofish
Gracias por salvarme alguna vez.
cpu_meltdown
9

Aquí hay una solución paso a paso:

  1. Añadir un script llamado run.pyen /home/bodacydo/work/projecty edición de esta manera:

    import programs.my_python_program
    programs.my_python_program.main()
    

    (reemplace main()con su método equivalente en my_python_program.)

  2. Ir /home/bodacydo/work/project
  3. correr run.py

Explicación: dado que Python agrega a PYTHONPATH la ruta de la secuencia de comandos desde la que se ejecuta , se run.pyagregará la ejecución /home/bodacydo/work/project. Y voilà , import foo.tasksse encontrará.

cyborg
fuente
8

Solución de ejemplo para agregar la biblioteca a su PYTHONPATH.

  1. Agregue la siguiente línea en su ~ / .bashrc o simplemente ejecútela directamente:

    export PYTHONPATH="$PYTHONPATH:$HOME/.python"
  2. Luego, vincule su biblioteca requerida a su carpeta ~ / .python, por ejemplo

    ln -s /home/user/work/project/foo ~/.python/
Kenorb
fuente
6

Una mejor solución que la configuración PYTHONPATHes usarpython -m module.path

Esto se configurará correctamente sys.path[0]y es una forma más confiable de ejecutar módulos.

Tengo una reseña rápida sobre este problema, ya que otros respondedores han mencionado que la razón de esto es que se python path/to/file.pycoloca path/toal principio de PYTHONPATH( sys.path).

Anthony Sottile
fuente
2

En mi mente, debo considerar que la foocarpeta es una biblioteca independiente. Es posible que desee considerar moverlo a la Lib\site-packagescarpeta dentro de una instalación de Python. Es posible que desee considerar agregar un foo.ptharchivo allí.

Sé que es una biblioteca ya que ./programs/my_python_program.pycontiene la siguiente línea:

from foo.tasks import my_function

Así que no importa que ./programssea ​​una carpeta hermana ./foo. Es el hecho de que my_python_program.pyse ejecuta como un script como este:

python ./programs/my_python_program.py

quamrana
fuente
0

Si tiene este problema al usar una versión instalada, al usar setup.py, asegúrese de que su módulo esté incluido dentropackages

setup(name='Your program',
    version='0.7.0',
    description='Your desccription',
    packages=['foo', 'foo.bar'], # add `foo.bar` here
Danon
fuente