it-swarm.com.de

ModuleNotFoundError: Kein Modul mit dem Namen '__main __. Xxxx'; '__main__' ist kein Paket

Ich versuche gerade in Python3 zu arbeiten und benutze absolute Importe, um ein Modul in ein anderes zu importieren, aber ich erhalte den Fehler ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package. Betrachten Sie diese Projektstruktur:

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")

Dann läuft python3 moduleA.py3 gibt den Fehler aus. Was muss hier geändert werden?

42
mpseligson

.moduleB Ist ein relativer Import. Relativ funktioniert nur, wenn das übergeordnete Modul zuerst importiert oder geladen wird. Das bedeutet, dass Sie proj irgendwo in Ihre aktuelle Laufzeitumgebung importieren müssen. Wenn Sie den Befehl python3 moduleA.py3 Verwenden, kann das übergeordnete Modul nicht importiert werden. Du kannst:

  • from proj.moduleB import moduleB ODER
  • Sie können ein weiteres Skript erstellen, beispielsweise run.py, Um from proj import moduleA Aufzurufen.

Viel Glück bei Ihrer Reise in das fantastische Land Python.

36

Neben der Antwort von md-sabuj-sarker gibt es ein wirklich gutes Beispiel in der Dokumentation zu Python-Modulen .

Das sagen die Dokumente über Intra-Package-Referenzen :

Beachten Sie, dass relative Importe auf dem Namen des aktuellen Moduls basieren. Da der Name des Hauptmoduls immer "__main__" Lautet, müssen für Module, die als Hauptmodul einer Python) - Anwendung verwendet werden sollen, immer absolute Importe verwendet werden.

Wenn Sie python3 moduleA.py3 Ausführen, wird moduleA als Hauptmodul verwendet, sodass die Verwendung des absoluten Imports die richtige Vorgehensweise ist.

Beachten Sie jedoch, dass dieser absolute Import (from package.module import something) Fehlschlägt, wenn das Paket aus irgendeinem Grund eine Moduldatei mit demselben Namen wie das Paket enthält (zumindest auf meinem Python) = 3.7) So würde es zum Beispiel fehlschlagen, wenn Sie haben (am Beispiel des OP):

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

in diesem Fall würden Sie Folgendes erhalten:

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

Alternativ können Sie den . In from .moduleB import Entfernen, wie vorgeschlagen hier und hier , was zu funktionieren scheint, obwohl mein PyCharm (2018.2 .4) markiert dies als "Nicht aufgelöste Referenz" und kann nicht automatisch vervollständigt werden.

17
djvg

Vorwort

Ich entwickle ein Projekt, das tatsächlich ein Python -Paket ist, das über pip installiert werden kann, aber auch eine Befehlszeilenschnittstelle enthält. Ich habe keine Probleme, mein Projekt nach der Installation mit pip install . Auszuführen, aber hey, wer macht das jedes Mal, nachdem etwas in einer der Projektdateien geändert wurde? Ich musste das Ganze durch einfaches python mypackage/main.py Laufen lassen.

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

Die verschiedenen Gesichter des gleichen Problems

Ich habe versucht, einige Funktionen in main.py Aus meinem common.py - Modul zu importieren. Ich habe verschiedene Konfigurationen ausprobiert, die unterschiedliche Fehler verursachten, und ich möchte meine Beobachtungen mit Ihnen teilen und auch für die Zukunft eine kurze Notiz für mich hinterlassen.

Relativer Import

Das erste, was ich versuchte, war ein relativer Import:

from .common import my_func

Ich habe meine Anwendung mit folgendem Befehl ausgeführt: python mypackage/main.py. Leider ergab dies folgenden Fehler:

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

Die Ursache für dieses Problem ist, dass der Befehl main.py Direkt von python ausgeführt wurde und somit zum Hauptmodul mit dem Namen __main__ Wurde. Wenn wir diese Informationen mit dem von uns verwendeten relativen Import verknüpfen, erhalten wir die Fehlermeldung __main__.common. Dies wird in der Python-Dokumentation erklärt:

Beachten Sie, dass relative Importe auf dem Namen des aktuellen Moduls basieren. Da der Name des Hauptmoduls immer __main__ Lautet, müssen für Module, die als Hauptmodul einer Python -Anwendung verwendet werden sollen, immer absolute Importe verwendet werden.

Als ich mein Paket mit pip install . Installiert und dann ausgeführt habe, hat es einwandfrei funktioniert. Ich konnte auch das Modul mypackage.main In eine Python Konsole importieren. Es sieht also so aus, als gäbe es nur ein Problem, wenn man es direkt ausführt.

Absoluter Import

Befolgen Sie die Anweisungen in der Dokumentation und ändern Sie die Importanweisung in etwas anderes:

from common import my_func

Wenn wir jetzt versuchen, dies wie zuvor auszuführen: python mypackage/main.py, Funktioniert es wie erwartet! Aber es gibt eine Einschränkung, wenn Sie wie ich etwas entwickeln, das als eigenständiges Befehlszeilentool fungieren muss, nachdem Sie es mit pip installiert haben. Ich habe mein Paket mit pip install . Installiert und dann versucht, es auszuführen ...

ModuleNotFoundError: No module named 'common'

Was ist schlimmer, als ich eine Python Konsole geöffnet und versucht habe, das main Modul manuell zu importieren (import mypackage.main), Habe ich den gleichen Fehler wie oben erhalten. Der Grund dafür ist einfach: common ist kein relativer Import mehr, daher versucht Python, ihn in installierten Paketen zu finden. Wir haben kein solches Paket, deshalb schlägt es fehl.

Die Lösung mit einem absoluten Import funktioniert nur, wenn Sie eine typische Python App erstellen, die mit einem python Befehl ausgeführt wird.

Import mit einem Paketnamen

Es gibt auch eine dritte Möglichkeit, das common Modul zu importieren:

from mypackage.common import my_func

Dies unterscheidet sich nicht sehr von dem Ansatz Relativer Import, solange wir dies aus dem Kontext von mypackage tun. Und wieder endet der Versuch, dies mit python mypackage/main.py Auszuführen, ähnlich:

ModuleNotFoundError: No module named 'mypackage'

Wie irritierend das sein könnte, der Interpreter hat Recht, Sie haben ein solches Paket nicht installiert.

Die Lösung

Für einfache Python Apps

Verwenden Sie einfach absolute Importe (ohne den Punkt), und alles wird gut.

Für installierbare Python Apps in der Entwicklung

Verwenden Sie relative Importe oder Importe mit einem Paketnamen am Anfang, da Sie diese bei der Installation Ihrer App benötigen. Wenn es darum geht, ein solches Modul in der Entwicklung auszuführen, kann Python mit der Option -m Ausgeführt werden:

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

Also mache es statt python mypackage/main.py So: python -m mypackage.main.

1
itachi

Möglicherweise können Sie dies tun, bevor Sie das Modul importieren:

moduleA.py3

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

from moduleB import ModuleB
ModuleB.hello()

Fügen Sie das aktuelle Verzeichnis zum Umgebungsverzeichnis hinzu

0
Toby