842 Stimmen

Wie behebt man "Attempted relative import in non-package" auch mit __init__.py

Ich versuche zu folgen PEP 328 mit der folgenden Verzeichnisstruktur:

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

Unter core_test.py Ich habe die folgende Importanweisung

from ..components.core import GameLoopEvents

Bei der Ausführung erhalte ich jedoch die folgende Fehlermeldung:

tests$ python core_test.py 
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

Bei meiner Suche fand ich " Relativer Pfad funktioniert auch mit __init__.py nicht " und " Importieren eines Moduls aus einem relativen Pfad ", aber sie haben nicht geholfen.

Gibt es etwas, das ich hier übersehe?

688voto

BrenBarn Punkte 228691

Zur Erläuterung Ignacio Vazquez-Abrams's Antwort:

Der Python-Import-Mechanismus funktioniert relativ zum __name__ der aktuellen Datei. Wenn Sie eine Datei direkt ausführen, hat sie nicht ihren üblichen Namen, sondern den Namen "__main__" als seinen Namen. Relative Importe funktionieren also nicht.

Sie können es, wie von Igancio vorgeschlagen, mit der Methode -m Option. Wenn Sie einen Teil Ihres Pakets als Skript ausführen wollen, können Sie auch die Option __package__ Attribut, um der Datei mitzuteilen, welchen Namen sie in der Pakethierarchie haben soll.

Véase http://www.python.org/dev/peps/pep-0366/ für Einzelheiten.

475voto

Ignacio Vazquez-Abrams Punkte 735200

Ja. Sie verwenden es nicht als Paket.

python -m pkg.tests.core_test

233voto

Paolo Rovelli Punkte 8750

Es hängt davon ab, wie Sie Ihr Skript starten wollen.

Wenn Sie möchten, dass Starten Sie Ihren UnitTest über die Befehlszeile Das heißt, auf klassische Weise:

python tests/core_test.py

Da in diesem Fall Komponenten y Tests Geschwisterordner sind, können Sie das entsprechende Modul entweder mit der Option einfügen. oder die anhängen. Methode der sys.path Modul. Etwas wie:

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

Andernfalls können Sie Ihr Skript mit dem Argument '-m' starten (Beachten Sie, dass es sich in diesem Fall um ein Paket handelt, und Sie daher nicht die '.py' Erweiterung), das heißt:

python -m pkg.tests.core_test

In einem solchen Fall können Sie einfach den relativen Import verwenden, wie Sie es bisher getan haben:

from ..components.core import GameLoopEvents

Schließlich können Sie die beiden Ansätze mischen, so dass Ihr Skript unabhängig von der Art des Aufrufs funktioniert. Zum Beispiel:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents

214voto

ihm Punkte 2351

Sie können verwenden import components.core direkt, wenn Sie das aktuelle Verzeichnis an sys.path :

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

33voto

Allan Mwesigwa Punkte 1017

Führen Sie in core_test.py folgende Schritte aus:

import sys
sys.path.append('../components')
from core import GameLoopEvents

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X