Relative Importe - ModuleNotFoundError: Kein Modul mit dem Namen x

177

Dies ist das erste Mal, dass ich mich wirklich hingesetzt und Python 3 ausprobiert habe und kläglich versage. Ich habe die folgenden zwei Dateien:

  1. test.py
  2. config.py

In config.py sind einige Funktionen sowie einige Variablen definiert. Ich habe es auf Folgendes reduziert:

config.py

debug = True

test.py

import config
print (config.debug)

Ich habe auch eine __init__.py

Ich erhalte jedoch den folgenden Fehler:

ModuleNotFoundError: No module named 'config'

Mir ist bewusst, dass die py3-Konvention absolute Importe verwendet:

from . import config

Dies führt jedoch zu folgendem Fehler:

ImportError: cannot import name 'config'

Ich weiß also nicht, was ich hier tun soll ... Jede Hilfe wird sehr geschätzt. :) :)

Blitzmann
quelle
Ich kann den Fehler nicht reproduzieren. Wie führen Sie diesen Code aus?
Copperfield
2
Ich führe es im Leerlauf aus, der mit Python kommt, und auch als python test.py, und es funktioniert einwandfrei. Ich habe kein pyCharm, aber vielleicht ist eine schlechte Konfiguration von pyCharm, die das Problem verursacht
Copperfield
1
Sehr komisch. Ich benutze WinPython - lade einfach Vanilla Python 3.6 von python.org herunter und es funktioniert gut. Ich hätte nie gedacht, den Dolmetscher zu überprüfen! Vielen Dank!
Blitzmann
1
Ich vermute, dass mit PYTHONPATH etwas Funky los ist. Überprüfen Sie Ihre IDE-Einstellungen und / oder Systemumgebungsvariablen.
Martin Tournoij
1
Ich habe genau das gleiche Problem. Es ist kein Pycharm! Es ist Python3. Es funktioniert in Python2, aber wenn Sie Python3 verwenden, sehen Sie diesen Fehler! sehr frustrierend.

Antworten:

163

TL; DR: Sie können keine relativen Importe aus der von Ihnen ausgeführten Datei durchführen , da das __main__Modul nicht Teil eines Pakets ist.

Absolute Importe - Importieren Sie etwas, das auf verfügbar istsys.path

Relative Importe - Importieren Sie etwas relativ zum aktuellen Modul, das Teil eines Pakets sein muss

Wenn Sie beide Varianten genau gleich ausführen, sollte eine davon funktionieren. Wie auch immer, hier ist ein Beispiel, das Ihnen helfen soll zu verstehen, was los ist. Fügen wir eine weitere main.pyDatei mit der gesamten Verzeichnisstruktur wie folgt hinzu :

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

Und aktualisieren wir test.py, um zu sehen, was los ist:

# config.py
debug = True


# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

Lassen Sie uns zuerst test.py ausführen:

$ python ryan/test.py
__main__
Relative import failed
True

Hier „Test“ ist das __main__Modul und weiß nichts über zu einem Paket gehört. Sollte import configjedoch funktionieren, da der ryanOrdner zu sys.path hinzugefügt wird.

Lassen Sie uns stattdessen main.py ausführen:

$ python main.py
ryan.test
True
Absolute import failed

Und hier befindet sich der Test innerhalb des "Ryan" -Pakets und kann relative Importe durchführen. import configschlägt fehl, da implizite relative Importe in Python 3 nicht zulässig sind.

Hoffe das hat geholfen.

PS: Wenn Sie bei Python 3 bleiben, werden __init__.pyDateien nicht mehr benötigt .

Igonato
quelle
3
Kann ich etwas tun, damit absolute Importe immer funktionieren? Wie, Anruf sys.path.append('/some/path/my_module')innerhalb von /some/path/my_module/__init__.py?
James T.
4
@ JamesT. Ja, es ist ziemlich üblich, Änderungen zur sys.pathLaufzeit vorzunehmen ( github.com/… ). Sie können auch die Umgebungsvariable PYTHONPATH festlegen.
Igonato
6
"Wenn Sie bei Python 3 bleiben, werden __init__.pyDateien nicht mehr benötigt ." Interessant. Können Sie das näher erläutern? Ich hatte den Eindruck, dass sich der Mechanismus zur Paketauflösung zwischen 2 und 3 nicht allzu sehr geändert hat.
Kevin
2
"Wenn Sie bei Python 3 bleiben, werden keine __init__.pyDateien mehr benötigt ." Können Sie umgekehrt beschreiben, ob ein Paket sowohl in 2 als auch in 3 funktionieren soll? Und sehen Sie sich das leider veraltete Jahr 2009 an. Wofür ist das __init__.py? und seine am besten bewertete Antwort "Es ist ein Teil eines Pakets" . Wir müssen überall und oft die Unterscheidung zwischen "regulärem Paket [alt, vor 3.3]" und "Namespace-Paket [3.3+]" hervorheben .
smci
61

Ich habe es herausgefunden. Sehr frustrierend, besonders wenn man von Python2 kommt.

Sie müssen .dem Modul ein hinzufügen , unabhängig davon, ob es relativ oder absolut ist.

Ich habe das Verzeichnis wie folgt erstellt.

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

modx.py.

def does_something():
    return "I gave you this string."

mody.py.

from modx import does_something

def loaded():
    string = does_something()
    print(string)

main.py.

from lib import mody

mody.loaded()

Wenn ich main ausführe, passiert Folgendes

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

Ich lief 2to3, und die Kernausgabe war dies

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

Ich musste die Importanweisung von mody.py ändern, um das Problem zu beheben

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

Dann habe ich main.py erneut ausgeführt und die erwartete Ausgabe erhalten

$ python main.py
I gave you this string.

Zum Schluss nur, um es aufzuräumen und zwischen 2 und 3 tragbar zu machen.

from __future__ import absolute_import
from .modx import does_something

quelle
1
Es ist erwähnenswert, dass das try/exceptLadeverfahren die eigentliche Zutat ist, die hier funktioniert (wie einige Leute verwenden müssen try:scripts.modxund except: modx), und was dieses Problem für mich gelöst hat.
Justapigeon
40

Das Einstellen von PYTHONPATH kann ebenfalls bei diesem Problem helfen.

So geht's unter Windows

set PYTHONPATH=.

Santosh Pillai
quelle
11
Das Setzen von PYTHONPATH auf das Hauptcodeverzeichnis löste das Problem für mich!
Geek
1
Funktioniert auch unter Linux. exportiere PYTHONPATH =.
rjdkolb
28

Sie müssen den Pfad des Moduls anhängen PYTHONPATH.


Für UNIX (Linux, OSX, ...)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

Für Windows

set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\module\
Giorgos Myrianthous
quelle
4
Vielen Dank @Giorgos! Dies gilt insbesondere dann, wenn Sie versuchen, ein Stammverzeichnis in einem Docker-Image festzulegen.
Tony Fraser
15

Versuchte dein Beispiel

from . import config

hat den folgenden SystemError erhalten:
/usr/bin/python3.4 test.py
Traceback (letzter Aufruf zuletzt):
Datei "test.py", Zeile 1, in
from. import config
SystemError: Übergeordnetes Modul '' nicht geladen, relativer Import kann nicht durchgeführt werden


Das wird bei mir funktionieren:

import config
print('debug=%s'%config.debug)

>>>debug=True

Getestet mit Python: 3.4.2 - PyCharm 2016.3.2


Außerdem bietet Ihnen PyCharm an, diesen Namen zu importieren .
Sie müssen darauf klicken configund ein Hilfesymbol wird angezeigt. Geben Sie hier die Bildbeschreibung ein

stovfl
quelle
11

Sie können einfach die folgende Datei zu Ihrem Testverzeichnis hinzufügen, und Python führt sie dann vor den Tests aus

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
Vinod Rane
quelle
Genau das habe ich gesucht. Danke, dass du diese Antwort geteilt hast !!!
Mayur
Wenn Sie so etwas tun, wird ein Linter-Fehler (pylint3) angezeigt. Der Fehler ist ähnlich wie dieser. Dateiname.py:12:0: C0413: Der Import "import abc.def.ghi.file_util as file_util" sollte oben im Modul platziert werden (falsche Importposition)
Sharad
6

Legen Sie die PYTHONPATHUmgebungsvariable im Stammprojektverzeichnis fest.

In Anbetracht von UNIX-ähnlich:

export PYTHONPATH=.
Manasouza
quelle
4

Dieses Beispiel funktioniert unter Python 3.6.

Ich schlage vor, Run -> Edit Configurationsin PyCharm zu gehen, dort alle Einträge zu löschen und zu versuchen, den Code erneut über PyCharm auszuführen.

Wenn dies nicht funktioniert, überprüfen Sie Ihren Projektinterpreter (Einstellungen -> Projektinterpreter) und führen Sie die Konfigurationsstandards aus (Ausführen -> Konfigurationen bearbeiten ...).

Carson Crane
quelle
4

Deklarieren Sie die korrekte sys.path- Liste, bevor Sie das Modul aufrufen:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')
HoangYell
quelle
1

Wie in den Kommentaren zum ursprünglichen Beitrag angegeben, schien dies ein Problem mit dem Python-Interpreter zu sein, den ich aus irgendeinem Grund verwendete, und nicht mit den Python-Skripten. Ich habe vom WinPython-Bundle auf das offizielle Python 3.6 von python.org umgestellt und es hat einwandfrei funktioniert. danke für die hilfe an alle :)

Blitzmann
quelle
1
Hmm, ich hasse es, das zu sagen, aber mir ist das Gleiche passiert. Die Neuerstellung der Umgebung behebt das Problem. In meinem Fall wurde dieser Fehler beim Ausführen von Tests angezeigt. Versuchen Sie in derselben Umgebung, dasselbe Modul zu importieren. Die Wiederherstellungsumgebung hat sie alle behoben (gleiche Python-Version 3.6)
Naoko
1
Verschiedene IDEs haben unterschiedliche Arten, Pfade speziell für Projektquelldateien (Ansichten, Module, Vorlagen usw.) zu behandeln. Wenn Ihr Projekt richtig strukturiert und codiert ist, sollte es für alle (Standard-) IDEs funktionieren. Probleme mit gängigen IDEs wie WinPython bedeuten, dass das Problem tatsächlich von Ihrem Projekt herrührt. Wie oben erwähnt, lautet das Problem "Sie müssen dem Modul eine. Hinzufügen" von user3159377, was die akzeptierte Antwort sein sollte.
Winux
1

Wenn Sie Python 3+ verwenden, fügen Sie die folgenden Zeilen hinzu

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)
Vivek Garg
quelle
0

Versuchen

from . import config

Damit wird aus derselben Ordnerebene importiert. Wenn Sie direkt versuchen zu importieren, wird davon ausgegangen, dass es sich um einen Untergebenen handelt

Arny Boy
quelle