Module richtig laden mit importlib

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
YAPD
User
Beiträge: 120
Registriert: Dienstag 27. Juli 2021, 23:23
Wohnort: Frankfurt am Main

Hallo Zusammen,

ich habe mal eine Frage zum Import von Modulen mit importlib.
Ich habe folgenden Code :

Code: Alles auswählen

import importlib
import os

module = "Testumgebung::Defaults"  # Example 1 : WORKS
module = "Config::Test"                        # Example 2 : DOES NOT WORK

module_filename = module
module_filename = module_filename.replace("::", "/") + ".py"

if os.path.exists(os.getcwd() + "/" + module_filename) == False:
    print(f"[  ERROR  ] The Specified Module '{module}' Could Not Be Found !")

module_instance = importlib.import_module(module.replace("::", "."))
Nun habe ich eine Dateistruktur, die z. B. so aussieht :

Code: Alles auswählen

[ VTE ]
|--> Config
       |--> Test.py
|--> Testumgebung
       |--> Defaults.py
VTE.py
Config.py
Das Laden des Moduls 'Testumgebung::Defaults' ist erfolgreich.

Das Laden des Moduls 'Config::Test' scheitert allerdings mit folgender
Fehlermeldung :

Code: Alles auswählen

module_instance = importlib.import_module( module.replace( '::' , "." ) )
  File "D:\Anwendungen\Python\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 981, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'Config.Test'; 'Config' is not a package
Wie erreiche ich, dass importlib die Datei "Config::Test' lädt, obwohl bereits die Datei
'Config.py' im Stammverzeichnis exisitiert ?

Vielen Dank !

Viele Grüße
YAPD
-----
Yet Another Python Developer
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@YAPD: Gar nicht. Entweder Du hast ein Package oder ein Modul. Beides geht nicht. Und in die Unterverzeichnisse gehört jeweils eine `__init__.py`. Die kann leer sein, da kann aber auch der Inhalt der `Config.py` drin stehen.

Die Frage hat nichts mit `importlib` zu tun, lass doch bitte diesen unnötigen Unsinn endlich sein.

Pfade bearbeitet/erstellt man nicht mit Zeichenkettenoperationen sondern mit `pathlib.Path`. Module müssen weder aus *.py-Dateien kommen, noch im Dateisystem liegen, der Test ob die Datei existiert kann also fehlschlagen obwohl ein ``import`` funktionieren würde.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@YAPD: Und der Versuch irgendwelche Perl Modul-Schreibweisen irgendwie in Python zu prügeln wirkt schon sehr verzweifelt. Auch hier sei wieder die Frage gestattet: Warum soll das sinnvoll sein?
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@YAPD: Randbemerkung weil mir schon öfter sinnlose Zuweisung der Form ``name = anderer_name`` in Deinen Quelltexten aufgefallen sind: Bei Zuweisungen und Aufrufen kopiert Python niemals von sich aus Daten. Zudem sind Zeichenketten in Python unveränderbar. Das ist also beides anders als in Perl. Es in aller Regel keinen Sinn in einem Namensraum das *selbe* Objekt unter verschiedenen Namen zur Verfügung zu haben.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
YAPD
User
Beiträge: 120
Registriert: Dienstag 27. Juli 2021, 23:23
Wohnort: Frankfurt am Main

__blackjack__ hat geschrieben: Sonntag 4. Juni 2023, 15:05 Module müssen weder aus *.py-Dateien kommen, noch im Dateisystem liegen, der Test ob die Datei existiert kann also fehlschlagen obwohl ein ``import`` funktionieren würde.
Kannst du das bitte nochmal ausführen. Welche Möglichkeiten gibt es denn sonst noch ?
-----
Yet Another Python Developer
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@YAPD: Es gibt unendlich viele Möglichkeiten weil man sich in den Importmechanismus einklinken kann. Standardmässig können Module im Python-Interpreter fest einkompiliert sein, aus dem Dateisystem kommen, oder in ZIP-Archiven liegen. Und es muss auch keine *.py-Datei vorliegen, sondern es kann auch eine Bytecode-Datei oder (zumindest wenn die Datei tatsächlich auf dem Dateisystem liegt) eine native Bibliothek sein, die verschiedene Endungen haben kann, die zudem vom System abhängt.

Es gibt aber gar keinen Grund das vor dem Import zu prüfen, denn wenn man tatsächlich importiert, bekommt man ja eine Ausnahme falls das nicht klappt. Es macht keinen Sinn da selbst vorher irgendwie zu versuchen zu prüfen ob man denn importieren *könnte*, wenn diese Prüfung beim importieren sowieso schon gemacht wird.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@YAPD: Und, weil er in diesen Thread noch nicht gefallen ist, einmal mehr der Hinweis: Namen in Python schreibt man klein. Auch den von Modulen.
Benutzeravatar
YAPD
User
Beiträge: 120
Registriert: Dienstag 27. Juli 2021, 23:23
Wohnort: Frankfurt am Main

__blackjack__ hat geschrieben: Sonntag 4. Juni 2023, 15:05 @YAPD: Gar nicht. Entweder Du hast ein Package oder ein Modul. Beides geht nicht. Und in die Unterverzeichnisse gehört jeweils eine `__init__.py`. Die kann leer sein, da kann aber auch der Inhalt der `Config.py` drin stehen.

Die Frage hat nichts mit `importlib` zu tun, lass doch bitte diesen unnötigen Unsinn endlich sein.

Pfade bearbeitet/erstellt man nicht mit Zeichenkettenoperationen sondern mit `pathlib.Path`. Module müssen weder aus *.py-Dateien kommen, noch im Dateisystem liegen, der Test ob die Datei existiert kann also fehlschlagen obwohl ein ``import`` funktionieren würde.
Danke für die "Hilfe" und dafür, dass du mich 2 Seiten lang belehrt hast, anstatt mir einen Tipp für eine funktionierende Lösung zu geben, die im Prinzip nur aus Änderungen von 2 Zeilen im Zusammenhang mit importlib stehen. Aber da importlib ja mit dem allen gar nichts zu tun hat, kann das ja nicht sein. :lol: :roll:
Es gibt viele Python - Foren, in dem die User viel freundlicher und hilfsbereiter seid, als ihr "Experten" ( _blackjack_ , Sirius , Sparrow ). Und das zieht sich durch jeden Post von Euch auf dieser Seite. Erstmal 2 Seiten lang über jeglichen Mist beschweren anstatt zu helfen.
-----
Yet Another Python Developer
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich habe einen Tipp gegeben: die `__init__.py`. Und die Frage hat tatsächlich nichts mit `importlib` zu tun, denn das verwendet man nicht für normale Importe und auch nicht um neben einem Package noch ein gleichnamiges Modul liegen zu haben. Das ist verwirrend. Wenn Du jetzt an das Modul kommst, wie importierst Du denn dann das Package?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
YAPD
User
Beiträge: 120
Registriert: Dienstag 27. Juli 2021, 23:23
Wohnort: Frankfurt am Main

__blackjack__ hat geschrieben: Montag 5. Juni 2023, 20:26 Ich habe einen Tipp gegeben: die `__init__.py`. Und die Frage hat tatsächlich nichts mit `importlib` zu tun, denn das verwendet man nicht für normale Importe und auch nicht um neben einem Package noch ein gleichnamiges Modul liegen zu haben. Das ist verwirrend. Wenn Du jetzt an das Modul kommst, wie importierst Du denn dann das Package?
Im Grunde hat waren es 2 verschiedene Änderungen. Einerseits hat die '__init__.py" im Unterordner gefehlt. Diese ( leere ) Datei habe ich hinzugefügt.

Außerdem verwende ich nicht mehr die Funktion 'importlib.import_module( )', sondern die Funktionen :

importlib.util.spec_from_file_location
importlib.util.module_from_spec
loader.exec_module

Beispiel :

Code: Alles auswählen

        self.module_specs = importlib.util.spec_from_file_location(module_descriptor , module_filehandler)
        self.module_instance = importlib.util.module_from_spec(self.module_specs)
        self.module_specs.loader.exec_module(self.module_instance)
Nun werden die Module, auch im Unterordner Config mit dem gleichen Namen, korrekt geladen.

VG
-----
Yet Another Python Developer
Antworten