web-dev-qa-db-fra.com

ModuleNotFoundError: Aucun module nommé '__main __. Xxxx'; '__main__' n'est pas un paquet

J'essaie actuellement de travailler dans Python3 et d'utiliser des importations absolues pour importer un module dans un autre, mais l'erreur ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package. Considérez cette structure de projet:

proj
    __init__.py3 (empty)
    moduleA.py3
    moduleB.py3

moduleA.py3

from .moduleB import ModuleB
ModuleB.hello()

moduleB.py3

class ModuleB:
    def hello():
        print("hello world")

Ensuite, lancer python3 moduleA.py3 donne l'erreur. Qu'est-ce qui doit être changé ici?

42
mpseligson

.moduleB est une importation relative. Relative ne fonctionne que lorsque le module parent est importé ou chargé en premier. Cela signifie que vous devez importer proj quelque part dans votre environnement d'exécution actuel. Lorsque vous utilisez la commande python3 moduleA.py3, vous ne pouvez pas importer le module parent. Vous pouvez:

  • from proj.moduleB import moduleB OU
  • Vous pouvez créer un autre script, disons run.py, pour appeler from proj import moduleA

Bonne chance dans votre voyage au pays de Python.

36
Md. Sabuj Sarker

En plus de la réponse de md-sabuj-sarker, il existe un très bon exemple dans documentation sur les modules Python .

Voici ce que disent les docs sur intra-package-references :

Notez que les importations relatives sont basées sur le nom du module actuel. Le nom du module principal étant toujours "__main__", les modules destinés à être utilisés comme module principal d'une application Python doivent toujours utiliser des importations absolues.

Si vous exécutez python3 moduleA.py3, moduleA est utilisé comme module principal. L'utilisation de l'importation absolue semble donc être la meilleure chose à faire.

Cependant, sachez que cette importation absolue (from package.module import something) échoue si, pour une raison quelconque, le package contient un fichier de module portant le même nom que le package (au moins, sur mon Python 3.7). Ainsi, par exemple, cela échouera si vous avez (en utilisant l'exemple du PO):

proj/
    __init__.py (empty)
    proj.py (same name as package)
    moduleA.py
    moduleB.py

auquel cas vous obtiendriez:

ModuleNotFoundError: No module named 'proj.moduleB'; 'proj' is not a package

Vous pouvez également supprimer le . de from .moduleB import, comme suggéré ici et ici , ce qui semble fonctionner, bien que mon PyCharm (2018.2.4) ) marque ceci comme une "référence non résolue" et ne parvient pas à se compléter automatiquement.

17
djvg

Avant-propos

Je développe un projet qui est en fait un package Python pouvant être installé via pip , mais il expose également une commande interface de ligne. Je n'ai pas de problèmes à exécuter mon projet après l'avoir installé avec pip install ., mais bon, qui fait cela à chaque fois après avoir modifié quelque chose dans l'un des fichiers du projet? Il me fallait tout faire par python mypackage/main.py simple.

/my-project
    - README.md
    - setup.py
    /mypackage
      - __init__.py
      - main.py
      - common.py

Les différents visages d'un même problème

J'ai essayé d'importer quelques fonctions dans main.py à partir de mon module common.py. J'ai essayé différentes configurations qui ont donné des erreurs différentes, et je veux partager avec vous mes observations et laisser une note rapide pour moi aussi.

Importation relative

Le premier que j'ai essayé était une importation relative:

from .common import my_func

J'ai exécuté mon application avec simple: python mypackage/main.py. Malheureusement, cela a donné l'erreur suivante:

ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package

La cause de ce problème est que le main.py a été exécuté directement par la commande python, devenant ainsi le module principal nommé __main__. Si nous connectons ces informations à l'importation relative que nous avons utilisée, nous obtenons ce que nous avons dans le message d'erreur: __main__.common. Ceci est expliqué dans le documentation Python :

Notez que les importations relatives sont basées sur le nom du module actuel. Le nom du module principal étant toujours __main__, les modules destinés à être utilisés comme module principal d'une application Python doivent toujours utiliser des importations absolues.

Lorsque j'ai installé mon paquet avec pip install . et que je l'ai ensuite exécuté, cela a parfaitement fonctionné. J'ai également pu importer le module mypackage.main dans une console Python. Donc, il semble qu'il y ait un problème à l'exécuter directement.

Import absolu

Suivons les conseils de la documentation et changeons l'instruction d'importation en une autre:

from common import my_func

Si nous essayons maintenant d'exécuter ceci comme avant: python mypackage/main.py, alors cela fonctionnera comme prévu! Cependant, il y a une mise en garde lorsque, comme moi, vous développez quelque chose qui doit fonctionner comme un outil de ligne de commande autonome après l'avoir installé avec pip . J'ai installé mon paquet avec pip install . puis j'ai essayé de l'exécuter ...

ModuleNotFoundError: No module named 'common'

Pire encore, lorsque j'ai ouvert une console Python et tenté d'importer le module main manuellement (import mypackage.main), la même erreur que ci-dessus s'est produite. La raison en est simple: common n'est plus une importation relative, donc Python essaie de le trouver dans les packages installés. Nous n'avons pas un tel forfait, c'est pourquoi il échoue.

La solution avec une importation absolue ne fonctionne bien que lorsque vous créez une application Python typique exécutée avec une commande python.

Importer avec un nom de package

Il existe également une troisième possibilité pour importer le module common:

from mypackage.common import my_func

Ce n’est pas très différent de l’approche relative à l’importation relative , tant que nous le faisons à partir du contexte de mypackage. Et encore une fois, essayer de lancer ceci avec python mypackage/main.py se termine de la même manière:

ModuleNotFoundError: No module named 'mypackage'

Comme cela peut être irritant, l'interprète a raison, vous n'avez pas installé un tel logiciel.

La solution

Pour les simples Python applications

Il suffit d’utiliser des importations absolues (sans le point) et tout ira bien.

Pour les applications Python en cours de développement

Utilisez des importations relatives, ou des importations avec un nom de package au début, car vous en avez besoin de cette manière lors de l'installation de votre application. Quand il s'agit d'exécuter un tel module en développement, Python peut être exécuté avec l'option -m:

-m mod : run library module as a script (terminates option list)

Ainsi, au lieu de python mypackage/main.py, procédez comme suit: python -m mypackage.main.

1
itachi

Peut-être que vous pouvez le faire avant d'importer le module:

moduleA.py3

import os
import re
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from moduleB import ModuleB
ModuleB.hello()

Ajouter le répertoire en cours au répertoire de l'environnement

0
Toby