Python Modul aus String mit Code importieren?
Moin,
ich habe ein Pythonprogramm, das aus mehreren Dateien besteht. Das Hauptskript importiert diese dann.
Nun bräuchte ich leider aber mein gesamtes Programm als ein einzelnes Pythonskript. Heißt, ich möchte nur eine .py-Datei (fragt einfach nicht wieso, das ist kompliziert und nicht relevant).
Ich würde also gerne ein Modul importieren, aus dem Quellcode heraus, den ich als String vorliegen habe.
Die importlib-Bibliothek hat unter importlib.abc.InspectLoader eine Methode source_to_code(). Damit kann man doch sicherlich arbeiten. Leider habe ich mit importlib bisher nicht viel Erfahrung gemacht. Besagte Funktion gibt ein code-Objekt wieder. Mit welchen weiteren Methoden könnte ich dies dann importieren?
Die zwei offensichtlichen Alternativen kommen für mich leider nicht infrage:
- Den Quellcode aus dem String in eine temporäre Datei schreiben und von da importieren
- Den Quellcode einfach so in das Hauptskript kopieren (ich importiere mehrere meiner eigenen Module, und einige haben Methoden mit gleichen Namen)
Meine Frage also nochmal kurzgefasst: Anstatt ein Modul aus einer anderen Pythondatei zu importieren, möchte ich es aus dem Inhalt jener Pythondatei importieren, der als String vorliegt, anstatt in einer separaten Datei.
1 Antwort
Du willst also ein Problem, über das du nicht bereit bist im Detail darüber zu sprechen mit einer unsicheren und unwartbaren Programmiermethode lösen und gestattest dann nicht einmal, die Gründe zu hinterfragen? Ich bin mir sicher, es gibt bestimmt eine andere, bessere Vorgehensweise um dein Ziel zu erreichen. Solange dieses aber nicht klar ist ...
Aufgrund Aussagen wie:
fragt einfach nicht wieso, das ist kompliziert und nicht relevant
bin ich raus
Wenn du doch mit dem Kopf durch die Wand willst, vergiss die importlib, die brauchst du nicht. Es gibt die exec() Funktion:
https://www.programiz.com/python-programming/methods/built-in/exec
Exec wäre problematisch, da ich ja mehrere Module mit gleich benannten Methoden habe <3
Ich hab's inzwischen aber auch selber geschafft!
import importlib.abc
import importlib.util
# Der Code von Skript A als String
script_code = """
def say_hello():
print("Hallo von Skript A!")
"""
# Ein Dummy-Modulnamen erstellen
module_name = 'temp_module'
# Eine Klasse erstellen, die die InspectLoader-Methode implementiert
class StringLoader(importlib.abc.InspectLoader, importlib.abc.Loader):
def create_module(self, spec):
return None
def exec_module(self, module):
code = self.source_to_code(script_code)
exec(code, module.__dict__)
def get_code(self, fullname):
return self.source_to_code(script_code)
def get_source(self, fullname):
return script_code
def load_module(self, fullname):
spec = importlib.util.spec_from_loader(fullname, self)
module = importlib.util.module_from_spec(spec)
self.exec_module(module)
return module
# Ein Modul erstellen
loader = StringLoader()
temp_module = loader.load_module(module_name)
# Die Funktion aus dem importierten Modul aufrufen
temp_module.say_hello()
(Falls jemand in Zukunft hierüber stolpert, bitte sehr)