it-swarm.com.de

Relative Importe zum milliardsten Mal

Ich war hier:

und viele URLs, die ich nicht kopiert habe, manche auf SO, andere auf anderen Websites, als ich dachte, ich hätte die Lösung schnell.

Die immer wiederkehrende Frage ist folgende: Wie löse ich diese 32-Bit-Version von Python 2.7.3 unter Windows 7, um diese Meldung "Versuchter relativer Import in Nichtpaketen" zu lösen? Ich habe eine genaue Nachbildung des Pakets auf pep-0328 erstellt:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

Ich habe Funktionen namens Spam und Eier in den entsprechenden Modulen erstellt. Natürlich hat es nicht funktioniert. Die Antwort ist anscheinend in der 4. URL, die ich aufgeführt habe, aber es ist alles Alumni für mich. Diese Antwort war auf einer der URLs, die ich besucht habe:

Relative Importe verwenden das Namensattribut eines Moduls, um die Position dieses Moduls in der Pakethierarchie zu bestimmen. Wenn der Name des Moduls keine Paketinformationen enthält (z. B. "main"), werden relative Importe so aufgelöst, als ob das Modul ein Modul der obersten Ebene wäre, unabhängig davon, wo sich das Modul tatsächlich im Dateisystem befindet.

Die obige Antwort sieht vielversprechend aus, aber für mich sind das alles Hieroglyphen. Also meine Frage, wie kann ich Python dazu bringen, mir nicht "Versuchter relativer Import in Nicht-Paket" zurückzugeben? hat eine Antwort, die -m angeblich beinhaltet.

Kann mir jemand bitte sagen, warum Python diese Fehlermeldung gibt, was es bedeutet, dass es kein Paket ist!, Warum und wie definieren Sie ein 'Paket' und die genaue Antwort ist leicht genug ein Kindergärtner zu verstehen

Bearbeiten: Die Importe wurden von der Konsole aus vorgenommen.

367
user1881400

Skript vs. Modul

Hier ist eine Erklärung. Die Kurzversion besteht darin, dass es einen großen Unterschied zwischen dem direkten Ausführen einer Python -Datei und dem Importieren dieser Datei von einem anderen Ort gibt. Nur zu wissen, in welchem ​​Verzeichnis sich eine Datei befindet, bestimmt nicht, in welchem ​​Paket Python sie sich befindet. Dies hängt außerdem davon ab, wie Sie die Datei in Pythonladen. _ (durch Ausführen oder durch Importieren).

Es gibt zwei Möglichkeiten, eine Python -Datei zu laden: als Skript der obersten Ebene oder als Modul. Eine Datei wird als Skript der obersten Ebene geladen, wenn Sie sie direkt ausführen, indem Sie beispielsweise python myfile.py in die Befehlszeile eingeben. Es wird als Modul geladen, wenn Sie python -m myfile ausführen, oder wenn es geladen wird, wenn eine import -Anweisung in einer anderen Datei gefunden wird. Es kann jeweils nur ein Skript der obersten Ebene vorhanden sein. Das Skript der obersten Ebene ist die Python -Datei, die Sie zum Starten ausgeführt haben.

Benennung

Wenn eine Datei geladen wird, erhält sie einen Namen (der in ihrem __name__ -Attribut gespeichert ist). Wenn es als Skript der obersten Ebene geladen wurde, lautet sein Name __main__. Wenn es als Modul geladen wurde, ist sein Name der Dateiname, dem die durch Punkte getrennten Namen aller Pakete/Unterpakete vorangestellt sind, zu denen es gehört.

So zum Beispiel in Ihrem Beispiel:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

wenn Sie moduleX (Anmerkung: importiert , nicht direkt ausgeführt), würde der Name package.subpackage1.moduleX lauten. Wenn Sie moduleA importieren, lautet der Name package.moduleA. Wenn Sie jedoch direkt moduleX über die Befehlszeile ausführen, lautet der Name stattdessen __main__, und wenn Sie direkt ausführen moduleA in der Befehlszeile lautet der Name __main__. Wenn ein Modul als Skript der obersten Ebene ausgeführt wird, verliert es seinen normalen Namen und heißt stattdessen __main__.

Zugriff auf ein Modul NICHT über das enthaltene Paket

Es gibt noch einen weiteren Nachteil: Der Name des Moduls hängt davon ab, ob es "direkt" aus dem Verzeichnis, in dem es sich befindet, oder über ein Paket importiert wurde. Dies macht nur dann einen Unterschied, wenn Sie Python in einem Verzeichnis ausführen und versuchen, eine Datei in dasselbe Verzeichnis (oder ein Unterverzeichnis davon) zu importieren. Wenn Sie beispielsweise den Interpreter Python im Verzeichnis package/subpackage1 starten und dann import moduleX ausführen, lautet der Name von moduleX nur moduleX und nicht package.subpackage1.moduleX. Dies liegt daran, dass Python das aktuelle Verzeichnis beim Start zu seinem Suchpfad hinzufügt. Wenn das zu importierende Modul im aktuellen Verzeichnis gefunden wird, weiß es nicht, dass dieses Verzeichnis Teil eines Pakets ist, und die Paketinformationen werden nicht Teil des Modulnamens.

Ein Sonderfall ist, wenn Sie den Interpreter interaktiv ausführen (z. B. geben Sie einfach python ein und geben Sie Python Code direkt ein). In diesem Fall lautet der Name dieser interaktiven Sitzung __main__.

Hier ist das Entscheidende für Ihre Fehlermeldung: Wenn der Name eines Moduls keine Punkte enthält, wird es nicht als Teil eines Pakets betrachtet.. Es spielt keine Rolle, wo sich die Datei tatsächlich auf der Festplatte befindet. Alles, was zählt, ist der Name und der Name hängt davon ab, wie Sie ihn geladen haben.

Schauen Sie sich nun das Zitat an, das Sie in Ihrer Frage angegeben haben:

Relative Importe verwenden das Namensattribut eines Moduls, um die Position dieses Moduls in der Pakethierarchie zu bestimmen. Wenn der Name des Moduls keine Paketinformationen enthält (z. B. 'main'), werden relative Importe so aufgelöst, als wäre das Modul ein Modul der obersten Ebene, unabhängig davon, wo sich das Modul tatsächlich im Dateisystem befindet.

Relative Importe ...

Relative Importe verwenden den Namen des Moduls , um zu bestimmen, wo es sich in einem Paket befindet. Wenn Sie einen relativen Import wie from .. import foo verwenden, zeigen die Punkte an, dass die Anzahl der Ebenen in der Pakethierarchie erhöht werden soll. Wenn der Name Ihres aktuellen Moduls beispielsweise package.subpackage1.moduleX lautet, bedeutet ..moduleApackage.moduleA. Damit ein from .. import funktioniert, muss der Name des Moduls mindestens so viele Punkte enthalten, wie in der import -Anweisung enthalten sind.

... sind nur in einem Paket relativ

Lautet der Name Ihres Moduls jedoch __main__, wird davon ausgegangen, dass es sich nicht in einem Paket befindet. Sein Name enthält keine Punkte, und daher können Sie darin keine from .. import -Anweisungen verwenden. Wenn Sie dies versuchen, wird der Fehler "relative-import in non-package" angezeigt.

Skripte können keine relativen importieren

Sie haben wahrscheinlich versucht, moduleX oder ähnliches über die Befehlszeile auszuführen. Dabei wurde der Name auf __main__ gesetzt, was bedeutet, dass der relative Import fehlschlägt, da der Name nicht anzeigt, dass er sich in einem Paket befindet. Beachten Sie, dass dies auch passiert, wenn Sie Python aus demselben Verzeichnis ausführen, in dem sich ein Modul befindet, und dann versuchen, dieses Modul zu importieren, da Python das Modul wie oben beschrieben findet im aktuellen Verzeichnis "zu früh", ohne es zu merken, ist Teil eines Pakets.

Denken Sie auch daran, dass der "Name" dieser interaktiven Sitzung beim Ausführen des interaktiven Interpreters immer __main__ lautet. Also Sie können keine relativen Importe direkt aus einer interaktiven Sitzung durchführen. Relative Importe können nur in Moduldateien verwendet werden.

Zwei Lösungen:

  1. Wenn Sie wirklich moduleX direkt ausführen möchten, aber dennoch möchten, dass es als Teil eines Pakets betrachtet wird, können Sie python -m package.subpackage1.moduleX ausführen. Der -m weist Python an, es als Modul und nicht als Skript der obersten Ebene zu laden.

  2. Oder vielleicht möchten Sie nicht ausführen moduleX, Sie möchten nur ein anderes Skript ausführen, sagen myfile.py, dass Funktionen innerhalb von moduleX verwendet. Wenn dies der Fall ist, setzen Sie myfile.py an eine andere Stelle - nicht im package Verzeichnis - und starte es. Wenn Sie in myfile.py Dinge wie from package.moduleA import spam tun, funktioniert dies einwandfrei.

Notizen

  • Für jede dieser Lösungen muss das Paketverzeichnis (package in Ihrem Beispiel) über den Modul-Suchpfad Python (sys.path) zugänglich sein. Ist dies nicht der Fall, können Sie die im Paket enthaltenen Informationen überhaupt nicht zuverlässig verwenden.

  • Seit Python 2.6 wird der "Name" des Moduls für Zwecke der Paketauflösung nicht nur durch seine __name__ -Attribute, sondern auch durch das __package__ -Attribut bestimmt. Deshalb vermeide ich es, das explizite Symbol __name__ zu verwenden, um auf den "Namen" des Moduls zu verweisen. Seit Python 2.6 ist der "Name" eines Moduls effektiv __package__ + '.' + __name__ oder nur __name__, wenn __package__None ist.)

766
BrenBarn

Dies ist wirklich ein Problem innerhalb von Python. Der Ursprung der Verwirrung ist, dass die Leute den relativen Import irrtümlicherweise als relativen Pfad betrachten, der nicht der Fall ist.  

Zum Beispiel, wenn Sie in faa.py schreiben:

from .. import foo

Dies hat nur eine Bedeutung, wenn faa.py von python identifiziert und während der Ausführung als Teil eines Pakets geladen wurde. In diesem Fall ist der Name des Moduls für faa.py wäre beispielsweise some_packagename.faa. Wenn die Datei nur geladen wurde, weil sie sich im aktuellen Verzeichnis befindet, wenn Python ausgeführt wird, verweist der Name auf kein Paket, und der relative Import schlägt möglicherweise fehl. 

Eine einfache Lösung, um auf Module im aktuellen Verzeichnis zu verweisen, ist die Verwendung dieser Option:

if __package__ is None or __package__ == '':
    # uses current directory visibility
    import foo
else:
    # uses current package visibility
    from . import foo
17
Rami Ka.

Hier ist ein allgemeines Rezept, das so modifiziert wurde, dass es als Beispiel in den Umgang mit Python-Bibliotheken passt, die als Pakete geschrieben wurden und voneinander abhängige Dateien enthalten, in denen ich Teile davon stückweise testen möchte. Nennen wir diesen lib.foo und sagen, dass er für die Funktionen lib.fileA und f1 und f2 für die Klasse lib.fileB Zugriff auf Class3 benötigt.

Ich habe ein paar print-Aufrufe aufgenommen, um zu veranschaulichen, wie das funktioniert. In der Praxis möchten Sie sie entfernen (und möglicherweise auch die from __future__ import print_function-Zeile).

Dieses spezielle Beispiel ist zu einfach, um zu zeigen, wann wirklich ein Eintrag in sys.path eingefügt werden muss. (Siehe Lars 'Antwort für einen Fall, in dem do es benötigt, wenn wir zwei oder mehr Ebenen von Paketverzeichnissen haben und dann os.path.dirname(os.path.dirname(__file__))— verwenden, aber es ist nicht wirklich hurt auch hier.) Es ist auch sicher genug, dies ohne den if _i in sys.path-Test zu tun. Wenn jedoch für jede importierte Datei derselbe Pfad eingefügt wird, beispielsweise wenn sowohl fileA als auch fileB Dienstprogramme aus dem Paket importieren möchten, wird sys.path mit demselben Pfad mehrfach verstopft. Daher ist es sinnvoll, if _i not in sys.path in der Zwischenablage zu haben.

from __future__ import print_function # only when showing how this works

if __package__:
    print('Package named {!r}; __is {!r}'.format(__package__, __name__))
    from .fileA import f1, f2
    from .fileB import Class3
else:
    print('Not a package; __is {!r}'.format(__name__))
    # these next steps should be used only with care and if needed
    # (remove the sys.path manipulation for simple cases!)
    import os, sys
    _i = os.path.dirname(os.path.abspath(__file__))
    if _i not in sys.path:
        print('inserting {!r} into sys.path'.format(_i))
        sys.path.insert(0, _i)
    else:
        print('{!r} is already in sys.path'.format(_i))
    del _i # clean up global name space

    from fileA import f1, f2
    from fileB import Class3

... all the code as usual ...

if __== '__main__':
    import doctest, sys
    ret = doctest.testmod()
    sys.exit(0 if ret.failed == 0 else 1)

Die Idee hier ist die folgende (und beachten Sie, dass diese über Python2.7 und Python 3.x alle gleich funktionieren):

  1. Wenn Sie als import lib oder from lib import foo als regulärer Paketimport aus normalem Code ausgeführt werden, ist __packagelib und __name__lib.foo. Wir nehmen den ersten Codepfad, importieren von .fileA usw.

  2. Bei Ausführung als python lib/foo.py ist __package__ Keine und __name__ wird __main__ sein.

    Wir nehmen den zweiten Codepfad. Das Verzeichnis lib befindet sich bereits in sys.path, so dass Sie es nicht hinzufügen müssen. Wir importieren aus fileA usw.

  3. Wenn Sie im Verzeichnis lib als python foo.py ausgeführt werden, verhält es sich wie in Fall 2.

  4. Wenn das Verzeichnis lib als python -m foo ausgeführt wird, ist das Verhalten ähnlich wie in den Fällen 2 und 3. Da der Pfad zum lib-Verzeichnis jedoch nicht in sys.path enthalten ist, fügen wir ihn vor dem Import hinzu. Dasselbe gilt, wenn wir Python und dann import foo ausführen.

    (Da .in sys.path ist, müssen Sie hier nicht unbedingt die absolute Version des Pfads hinzufügen. Hier macht eine tiefere Paketverschachtelungsstruktur, in der from ..otherlib.fileC import ... ausgeführt werden soll, einen Unterschied. Wenn Sie ' Wenn Sie dies nicht tun, können Sie die gesamte sys.path-Manipulation vollständig weglassen.)

Anmerkungen

Es gibt immer noch eine List. Wenn Sie das Ganze von außen laufen lassen:

$ python2 lib.foo

oder:

$ python3 lib.foo

das Verhalten hängt vom Inhalt von lib/__init__.py ab. Wenn das existiert und leer ist, ist alles gut:

Package named 'lib'; __is '__main__'

Wenn lib/__init__.pyselbstroutine importiert, sodass routine.name direkt als lib.name exportiert werden kann, erhalten Sie Folgendes:

$ python2 lib.foo
Package named 'lib'; __is 'lib.foo'
Package named 'lib'; __is '__main__'

Das Modul wird also zweimal importiert, einmal über das Paket und dann erneut als __main__, damit der main-Code ausgeführt wird. Python 3.6 und höher warnen davor:

$ python3 lib.routine
Package named 'lib'; __is 'lib.foo'
[...]/runpy.py:125: RuntimeWarning: 'lib.foo' found in sys.modules
after import of package 'lib', but prior to execution of 'lib.foo';
this may result in unpredictable behaviour
  warn(RuntimeWarning(msg))
Package named 'lib'; __is '__main__'

Die Warnung warning ist neu, das Verhalten bei Warnung jedoch nicht. Es ist Teil dessen, was manche die doppelte Importfalle nennen. (Weitere Einzelheiten siehe Ausgabe 27487 .) Nick Coghlan sagt:

Dieser nächste Trap ist in allen aktuellen Python-Versionen, einschließlich 3.3, vorhanden und kann in der folgenden allgemeinen Richtlinie zusammengefasst werden: "Fügen Sie niemals ein Paketverzeichnis oder ein Verzeichnis innerhalb eines Pakets direkt dem Python-Pfad hinzu".

Beachten Sie, dass, obwohl wir gegen diese Regel verstoßen, dies only ist, wenn die zu ladende Datei nicht als Teil eines Pakets ist und unsere Modifikation speziell darauf ausgelegt ist, auf andere Dateien in zuzugreifen dieses Paket. (Und wie ich bereits erwähnt habe, sollten wir dies wahrscheinlich nicht für Single-Level-Pakete tun.) Wenn wir extra sauber sein wollten, könnten wir dies wie folgt umschreiben:

    import os, sys
    _i = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    if _i not in sys.path:
        sys.path.insert(0, _i)
    else:
        _i = None

    from sub.fileA import f1, f2
    from sub.fileB import Class3

    if _i:
        sys.path.remove(_i)
    del _i

Das heißt, wir ändern sys.path lange genug, um unsere Importe zu erreichen, und setzen sie dann wieder so zurück, wie sie waren (Löschen einer Kopie von _i wenn und nur wenn wir eine Kopie von _i hinzugefügt haben).

3
torek

Nachdem ich mit vielen anderen darüber geredet hatte, stieß ich auf eine Notiz von Dorian B in diesem Artikel , die mein spezifisches Problem löste, in dem ich Module und Klassen für die Verwendung mit einem Web entwickelte Dienst, aber ich möchte auch in der Lage sein, sie während des Codierens mit den Debugger-Funktionen in PyCharm zu testen. Um Tests in einer eigenständigen Klasse auszuführen, füge ich am Ende meiner Klassendatei Folgendes hinzu:

if __== '__main__':
   # run test code here...

wenn ich jedoch andere Klassen oder Module in demselben Ordner importieren wollte, müsste ich dann alle meine Importanweisungen von relativen Notationen in lokale Verweise ändern (dh den Punkt (.) entfernen). Nachdem ich jedoch Dorians Vorschlag gelesen hatte, versuchte ich ' One-Liner 'und es hat funktioniert! Ich kann jetzt in PyCharm testen und meinen Testcode belassen, wenn ich die Klasse in einer anderen getesteten Klasse oder in meinem Webservice verwende!

# import any site-lib modules first, then...
import sys
parent_module = sys.modules['.'.join(__name__.split('.')[:-1]) or '__main__']
if __== '__main__' or parent_module.__== '__main__':
    from codex import Codex # these are in same folder as module under test!
    from dblogger import DbLogger
else:
    from .codex import Codex
    from .dblogger import DbLogger

Die if-Anweisung prüft, ob wir dieses Modul als main ausführen oder ob es in einem anderen Modul verwendet wird, das als main getestet wird. Vielleicht ist das offensichtlich, aber ich biete diese Notiz hier an, falls andere Personen, die von den oben genannten relativen Importproblemen frustriert sind, davon Gebrauch machen können.

3
Steve L

__name__ ändert sich abhängig davon, ob der betreffende Code im globalen Namespace oder als Teil eines importierten Moduls ausgeführt wird.

Wenn der Code nicht im globalen Bereich ausgeführt wird, ist __name__ der Name des Moduls. Wenn es im globalen Namespace ausgeführt wird, wenn Sie es beispielsweise in eine Konsole eingeben oder das Modul mit python.exe yourscriptnamehere.py als Skript ausführen, wird __name__ zu "__main__"

Mit if __== '__main__' wird viel Python-Code verwendet, um zu testen, ob der Code aus dem globalen Namespace ausgeführt wird. Dies ermöglicht Ihnen ein Modul, das sich als Skript eignet. 

Haben Sie versucht, diese Importe von der Konsole aus durchzuführen? 

2
theodox

Hier ist eine Lösung, die ich nicht empfehlen würde, aber in einigen Situationen nützlich sein könnte, in denen Module einfach nicht generiert wurden:

import os
import sys
parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir_name + "/your_dir")
import your_script
your_script.a_function()
2
Federico

Ich hatte ein ähnliches Problem, bei dem ich den Python-Modul-Suchpfad nicht ändern wollte und ein Modul relativ aus einem Skript laden musste (trotz "Skripts können nicht relativ importiert werden.) "wie BrenBarn oben schön erklärt hat).

Also habe ich den folgenden Hack benutzt. Leider ist es auf das imp-Modul angewiesen, das Seit Version 3.4 veraltet wurde, um zugunsten von importlib. Verworfen zu werden (ist dies auch mit importlib möglich? Ich weiß es nicht.) Der Hack funktioniert trotzdem jetzt.

Beispiel für den Zugriff auf Mitglieder von moduleX in subpackage1 von einem Skript aus im Ordner subpackage2:

#!/usr/bin/env python3

import inspect
import imp
import os

def get_script_dir(follow_symlinks=True):
    """
    Return directory of code defining this very function.
    Should work from a module as well as from a script.
    """
    script_path = inspect.getabsfile(get_script_dir)
    if follow_symlinks:
        script_path = os.path.realpath(script_path)
    return os.path.dirname(script_path)

# loading the module (hack, relying on deprecated imp-module)
PARENT_PATH = os.path.dirname(get_script_dir())
(x_file, x_path, x_desc) = imp.find_module('moduleX', [PARENT_PATH+'/'+'subpackage1'])
module_x = imp.load_module('subpackage1.moduleX', x_file, x_path, x_desc)

# importing a function and a value
function = module_x.my_function
VALUE = module_x.MY_CONST

Ein saubererer Ansatz scheint es zu sein, den sys.path zu ändern, der zum Laden von Modulen verwendet wird, wie von Federico erwähnt.

#!/usr/bin/env python3

if __== '__main__' and __package__ is None:
    from os import sys, path
    # __file__ should be defined in this case
    PARENT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
   sys.path.append(PARENT_DIR)
from subpackage1.moduleX import *
1
Lars

Relative Importe verwenden das Namensattribut eines Moduls, um die Position dieses Moduls in der Pakethierarchie zu bestimmen. Wenn der Name des Moduls keine Paketinformationen enthält (z. B. 'main'), werden relative Importe so aufgelöst, als wäre das Modul ein Modul der obersten Ebene, unabhängig davon, wo sich das Modul tatsächlich im Dateisystem befindet.

Schrieb ein kleines Python-Paket an PyPi, das den Zuschauern dieser Frage helfen könnte. Das Paket dient als Problemumgehung, wenn Sie Python-Dateien mit Importen ausführen möchten, die übergeordnete Pakete aus einem Paket/Projekt enthalten, ohne sich direkt im Verzeichnis der importierenden Datei zu befinden. https://pypi.org/project/import-anywhere/

1
ec2604

Um zu verhindern, dass Python an mich zurückgegeben wird, wurde versucht "relativer Import in Nicht-Paket versucht" . Package /

init . py Unterpaket1 / init . py moduleX.py moduleY.py Unterpaket2 / init . py moduleZ.py moduleA.py

Dieser Fehler tritt nur auf, wenn Sie den relativen Import auf die übergeordnete Datei anwenden. Zum Beispiel gibt die übergeordnete Datei bereits main zurück, nachdem Sie "print ( name )" in moduleA.py .so codiert haben. SO Diese Datei ist bereits main und kann kein übergeordnetes Paket weitergeben. .relative Importe sind in Dateien der Pakete subpackage1 und subpackage2.__ erforderlich. Sie können ".." verwenden, um auf das übergeordnete Verzeichnis oder das übergeordnete Modul zu verweisen. . Solche Dateien, bei denen Sie den relativen Import auf Eltern anwenden, können nur mit der Anwendung des absoluten Imports arbeiten. Wenn Sie ABSOLUTE IMPORT IN PARENT PACKAGE verwenden, wird KEIN FEHLER angezeigt, da Python weiß, wer sich auf der obersten Ebene des Pakets befindet, selbst wenn Ihr Die Datei ist in Unterpaketen enthalten, da PYTHON PATH die oberste Ebene des Projekts definiert 

0
Sakshi Jain

@ BrenBarn Antwort sagt alles, aber wenn Sie wie ich sind, könnte es eine Weile dauern, um zu verstehen. Hier ist mein Fall und wie die Antwort von @ BrenBarn darauf zutrifft, vielleicht hilft es Ihnen.

Der Fall

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

Verwenden Sie unser bekanntes Beispiel und fügen Sie hinzu, dass moduleX.py einen relativen Import zu ..moduleA hat. Vorausgesetzt, ich habe versucht, ein Testskript in das Verzeichnis subpackage1 zu schreiben, das moduleX importiert hat, habe dann aber den vom OP beschriebenen gefürchteten Fehler erhalten.

Lösung

Verschieben Sie das Testskript auf die gleiche Ebene wie package und importieren Sie package.subpackage1.moduleX

Erklärung

Wie erläutert, werden relative Importe relativ zum aktuellen Namen durchgeführt. Wenn mein Testskript moduleX aus demselben Verzeichnis importiert, lautet der Modulname in moduleX moduleX. Wenn ein relativer Import auftritt, kann der Interpreter die Pakethierarchie nicht sichern, da sie sich bereits oben befindet

Wenn ich moduleX von oben importiere, lautet der Name in moduleX package.subpackage1.moduleX und der relative Import kann gefunden werden

0
Brad Dre