Comment corriger l'erreur «ImportError: No module named…» en Python?

115

Quelle est la bonne façon de corriger cette erreur ImportError?

J'ai la structure de répertoires suivante:

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

Et je suis dans l'annuaire

/home/bodacydo/work/project

Maintenant si je tape

python ./programs/my_python_program.py

Je reçois instantanément

ImportError: No module named foo.tasks

Le ./programs/my_python_program.pycontient la ligne suivante:

from foo.tasks import my_function

Je ne peux pas comprendre pourquoi python ne trouvera pas ./foo/tasks.py- il est là.

Si je le fais à partir du shell Python, cela fonctionne:

python
>>> from foo.tasks import my_function

Cela ne fonctionne que si je l'appelle via un python ./programs/my_python_program.pyscript.

Bodacydo
la source

Réponses:

121

Python n'ajoute pas le répertoire courant sys.path, mais plutôt le répertoire dans lequel se trouve le script. Ajoutez /home/bodacydo/work/projectà l'un sys.pathou l' autre $PYTHONPATH.

Ignacio Vazquez-Abrams
la source
9
Alors, quel est l'intérêt d'avoir init .py dans le dossier racine? Cela semble ne servir à rien si vous modifiez sys.path ou pythonpath.
11
@Editor: __init__.pyindique uniquement que le répertoire doit être traité comme un package, lorsque son parent est dans sys.pathou est lui-même un package.
Ignacio Vazquez-Abrams
3
Vérifiez en outre les autorisations sur le dossier. C'était le problème dans mon cas.
SidJ
15
Pour ajouter le export PYTHONPATH=`pwd`
répertoire
1
Ce qui a fonctionné pour moi, c'est d'ajouter à $ PYTHONPATH le répertoire parent du projet, dans votre cas sera: /home/bodacydo/work... voir cette réponse
maledr53
33

Avez-vous un fichier appelé __init__.pydans le répertoire foo? Sinon, python ne reconnaîtra pas foo comme un package python.

Consultez la section sur les packages dans le didacticiel python pour plus d'informations.

Dave Kirby
la source
Merci et oui, j'ai eu __init__.py. Le problème cette fois était avec $PYTHONPATH. La solution d'Ignacio a fonctionné.
bodacydo
1
Les fichiers init .py sont nécessaires pour que Python traite les répertoires comme contenant des packages; ceci est fait pour empêcher les répertoires avec un nom commun, tel que string, de masquer involontairement les modules valides qui surviennent plus tard sur le chemin de recherche du module. Dans le cas le plus simple, init .py peut simplement être un fichier vide
panofish
Merci de m'avoir sauvé un jour.
cpu_meltdown
9

Voici une solution étape par étape:

  1. Ajouter un script appelé run.pydans /home/bodacydo/work/projectet modifier comme ceci:

    import programs.my_python_program
    programs.my_python_program.main()

    (remplacez main()par votre méthode équivalente dans my_python_program.)

  2. Aller à /home/bodacydo/work/project
  3. Courir run.py

Explication: Étant donné que python ajoute à PYTHONPATH le chemin du script à partir duquel il s'exécute , l'exécution run.pys'ajoutera /home/bodacydo/work/project. Et voilà , import foo.taskssera trouvé.

cyborg
la source
8

Exemple de solution pour ajouter la bibliothèque à votre PYTHONPATH.

  1. Ajoutez la ligne suivante dans votre ~ / .bashrc ou exécutez-la directement:

    export PYTHONPATH="$PYTHONPATH:$HOME/.python"
  2. Ensuite, liez votre bibliothèque requise dans votre dossier ~ / .python, par exemple

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

Une meilleure solution que le réglage PYTHONPATHconsiste à utiliserpython -m module.path

Cela sera correctement défini sys.path[0]et constitue un moyen plus fiable d'exécuter des modules.

J'ai un bref aperçu de ce problème, car d'autres répondants ont mentionné que la raison en est python path/to/file.pyplacée path/toau début du PYTHONPATH( sys.path).

Anthony Sottile
la source
2

Dans mon esprit, je dois considérer que le foodossier est une bibliothèque autonome. Je pourrais vouloir envisager de le déplacer dans le Lib\site-packagesdossier dans une installation python. Je pourrais envisager d'ajouter un foo.pthfichier là-bas.

Je sais que c'est une bibliothèque car le ./programs/my_python_program.pycontient la ligne suivante:

from foo.tasks import my_function

Donc, peu importe que ce ./programssoit un dossier frère ./foo. C'est le fait qu'il my_python_program.pysoit exécuté comme un script comme celui-ci:

python ./programs/my_python_program.py

quamrana
la source
0

Si vous rencontrez ce problème lors de l'utilisation d'une version installée, lors de l'utilisation setup.py, assurez-vous que votre module est inclus à l'intérieurpackages

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