Klassen erzeugen mit String/Variable

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
uschoen
User
Beiträge: 3
Registriert: Montag 14. November 2016, 09:48

Hallo,

ich stehe vor folgendem Problem und finde im Netz auch keine Lösung die Funktioniert. vielleicht hat hier jemand eine Lösung. Ich suche nache einer möglichkeit Klassen nicht anhand eines Namens zu erzeugen sondern anhand eines Strings (aus einer Variable). Hintergrund ist ein Config file wo div. Module aktiviert bzw deaktiviert werden. Eine Lösung währe :

File Struktur:
etc : konfig Files
gateway -> onewire: ds1820.py, hm_server.py
main.py

Klassen:
ds1820.py:
class server:
def __init__(self,args):
...mach was

hm_server.py:
class server:
dev __init__(self,args):
... mach auch was


main.py:

Code: Alles auswählen

from gateways.onewire import * #in der __init__.py werden alle verfügbaren module gepflegt als beispiel __all__ = ['ds1820', 'hm_server']

modul="ds1820"

if modul=="ds1820":
   modul_ds1820=ds1820.server("Argumente")
elseif modul=="hm_server":
  modul_hm_server=hm_server.server("Argumente)
else:
 print ("sorry unkown modul")
....
 
Soweit geht das, aber immer wenn ein neues Modul dazukommt müste ich den main.py Code entsprechend anpassen, und die Else IF Tabelle erweitern... sehr unschön. Das Laden der Module kann über die import * Funktion und der __init__.py schon mal automatisch erfolgen, auch wenn das vorgehen dazu sehr umstritten ist.
Ich würde gerne die Klassen anhand eines Config Files erzeugen. Ca so:

Code: Alles auswählen

from gateways.onewire import *

modul_to_load=["ds1820","hm_server"]
load_modul={}

for modul_name in modul_to_load:
	load_modul{modul_name}=modul_name.server(args)
... 
load_modul{'ds18201'}.machwas()

Es sind hir natürlich noch einige Prüfungen zu machen wie:
ist das Modul/Klasse importiert
wurde die Klasse erzeugt
...
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@uschoen: Deine Klassennamen halten sich nicht an die Namenskonvention, `server` ist für eine Klasse auch ein zu generischer Namen. Die einfachste Variante ist es, ein Wörterbuch mit allen möglichen Klassen zu führen:

# gateways.onewire.py

Code: Alles auswählen

class DS1820Server:
    [...]

class HmServer:
    [...]

ONEWIRE_SERVERS = {
    "ds1820": DS1820Server,
    "hm_server": HmServer,
}
und irgendwo anders:

Code: Alles auswählen

from gateways.onewire import ONEWIRE_SERVERS

modul = "ds1820"
onewire_server = ONEWIRE_SERVERS[modul](argumente)
Benutzeravatar
__LC__
User
Beiträge: 32
Registriert: Dienstag 1. März 2011, 14:08
Wohnort: 127.0.0.1
Kontaktdaten:

Ich weiß jetzt nicht ob ich deine Aufgabenstellung soweit verstanden habe, aber alternativ könntest du auch mit dem Modul 'importlib' arbeiten.

Code: Alles auswählen

import importlib

CLASS_NAME = 'DS1820Server'
ARGUMENTS = (1, 2, 3)

module = importlib.import_module('Onewire')

try:
    class_instance = getattr(module, CLASS_NAME)(*ARGUMENTS)
except AttributeError:
    pass
    # Hier die Behandlung der Exception
Schöne Grüße
__LC__
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@uschoen:
Was Du suchst, klingt sehr stark nach einem Pluginsystem. Das kannst Du mit einer Kombination von Sirius3s und __LC__s Antworten relativ einfach schnell erstellen (ungetestet):

Code: Alles auswählen

# file: XX.py - some plugin functionality
# some definitions
# ...
# interface is actual optional
# but a way to provide default entry symbols
PLUGIN_INTERFACE = {attrA: <some stuff from above>, ...}

# file: config.py
active_plugins = ['XX', 'YY', ...]

# file: plugin loader - provides plugin symbols as active_plugins[name].attrA ...
import config
import importlib
active_plugins = {name: importlib.import_module(name).PLUGIN_INTERFACE for name in config.active_plugins}
uschoen
User
Beiträge: 3
Registriert: Montag 14. November 2016, 09:48

Danke __LC__ !

habe mal deine Version einwenig ausgetestet... und abgewandelt, aber es läuft ! Ich denke die anderen Ansätze gehen bestimmt auch "viele wege führen nach ROM"...vielen Dank auch an die anderen. Nur die Lösung kann ich nachvollziehen... aber man wächst ja mit seinen Herrausforderungen...
Antworten