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?

14voto

Das Problem liegt bei Ihrer Prüfmethode,

Sie haben versucht python core_test.py

dann erhalten Sie diese Fehlermeldung WertFehler: Versuchter relativer Import in Nicht-Paket

Grund: Sie testen Ihre Verpackung aus einer anderen Quelle als der Verpackung.

also testen Sie Ihr Modul aus den Paketquellen.

wenn dies Ihre Projektstruktur ist,

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

cd pkg

python -m tests.core_test # dont use .py

oder von außerhalb pkg/

python -m pkg.tests.core_test

einzeln . wenn Sie aus einem Ordner im selben Verzeichnis importieren möchten. fügen Sie für jeden Schritt zurück einen weiteren hinzu.

hi/
  hello.py
how.py

in how.py

from .hi import hello

falls Sie how aus hello.py importieren möchten

from .. import how

12voto

deepak Punkte 1943

Wenn Ihr Anwendungsfall die Durchführung von Tests ist, und das scheint der Fall zu sein, dann können Sie Folgendes tun. Anstatt Ihr Testskript auszuführen als python core_test.py ein Test-Framework wie z. B. pytest . In der Befehlszeile können Sie dann Folgendes eingeben

$$ py.test

Dadurch werden die Tests in Ihrem Verzeichnis ausgeführt. Dies umgeht das Problem der __name__ unter __main__ Darauf wurde von @BrenBarn hingewiesen. Als nächstes setzen Sie ein leeres __init__.py Datei in Ihr Testverzeichnis, wodurch das Testverzeichnis Teil Ihres Pakets wird. Dann können Sie Folgendes tun

from ..components.core import GameLoopEvents

Wenn Sie Ihr Testskript jedoch als Hauptprogramm ausführen, wird es erneut fehlschlagen. Verwenden Sie also einfach den Test-Runner. Vielleicht funktioniert das auch mit anderen Testläufern wie z.B. nosetests aber ich habe es nicht überprüft. Hoffentlich hilft das.

9voto

v4gil Punkte 733

Meine schnelle Lösung besteht darin, das Verzeichnis zum Pfad hinzuzufügen:

import sys
sys.path.insert(0, '../components/')

8voto

suriyanto Punkte 1045

Da Sie bereits alles als Modul gekennzeichnet haben, ist es nicht notwendig, die relative Referenz zu verwenden, wenn Sie als Python-Modul starten.

Anstelle von

from ..components.core import GameLoopEvents

einfach

from pkg.components.core import GameLoopEvents

Wenn Sie vom Elternteil von pkg aus starten, verwenden Sie Folgendes

python -m pkg.tests.core_test

4voto

zhengcao Punkte 371

Als Paolo gesagt, haben wir 2 Aufrufmethoden:

1) python -m tests.core_test
2) python tests/core_test.py

Ein Unterschied zwischen ihnen ist die Zeichenfolge sys.path[0]. Da der Interpret sucht sys.path, wenn er importiert können wir mit tests/core_test.py :

if __name__ == '__main__':
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from components import core
    <other stuff>

Und danach können wir core_test.py mit anderen Methoden ausführen:

cd tests
python core_test.py
python -m core_test
...

Hinweis, nur py36 getestet.

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