Plugin-System mit Plugin-Basisklasse.

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
Jan-Nik
User
Beiträge: 5
Registriert: Sonntag 1. April 2007, 13:42
Kontaktdaten:

Sonntag 12. August 2007, 17:11

Ich versuche das Pluginsystem von gedit nach zubauen. Es stellt ein gedit-Modul bereit welches vom Plugin importiert werden muss. Nun erstellt es eine Klasse die von gedit.Plugin erbt. Diese wird von gedit instanziert und die activate-Methode wird aufgerufen.

So sieht mein Versuch aus:

gedit.py

Code: Alles auswählen

plugins = []
instances = []

class PluginMeta(type):
	def __new__(mcs, name, bases, dct):
		plugin = type.__new__(mcs, name, bases, dct)
		plugins.append(plugin)
		return plugin

class Plugin(object):
	__metaclass__ = PluginMeta
	def activate(self):
		raise NotImplementedError

if __name__ == '__main__':
	__import__('plugin')
	for plugin in plugins:
		if plugin != Plugin:
			instance = plugin()
			instance.activate()
			instances.append(instance)
plugin.py

Code: Alles auswählen

import gedit

class MyPlugin(gedit.Plugin):
	def __init__(self):
		gedit.Plugin.__init__(self)
	def activate(self):
		print 'Hello World'
Es passiert allerdings nichts (plugins ist leer). Das Problem scheint zu sein, das alle Variable von gedit.py zweimal existieren. Einmal für plugin.py und einmal für gedit.py, welches ich mit python gedit.py aufrufe. In der plugin.py-Version ist MyPlugin enthalten, aber wie komm ich da ran?

Wie kann ich Variablen "modul-übergreifend" definieren?
BlackJack

Sonntag 12. August 2007, 17:22

Wenn Du `gedit.py` als Programm startest, dann ist dass das `__main__`-Modul. Dort wird `plugin` importiert, das seinerseits `gedit` importiert und zwar wirklich *neu* importiert. Jetzt hast Du einmal `gedit.py` als `__main__` und ein *anderes* `gedit.py` als `gedit`.

Lösung: Den Plugin-Basis-Kram in ein eigenes Modul auslagern das nicht als Programm gestartet, sondern nur importiert wird.

Davon abgesehen sind zirkuläre importe, auch wenn sie so geschrieben sind, dass sie funktionieren, nicht besonders schön.
Jan-Nik
User
Beiträge: 5
Registriert: Sonntag 1. April 2007, 13:42
Kontaktdaten:

Sonntag 12. August 2007, 17:50

Vielen Dank! So funktioniert das jetzt auch mit subclasses, so habe ich es endgültig gemacht:

gedit.py

Code: Alles auswählen

class Plugin(object):
	pass
myplugin.py

Code: Alles auswählen

import gedit

class MyPlugin(gedit.Plugin):
	def __init__(self):
		gedit.Plugin.__init__(self)
	def activate(self):
		print 'Hello World'
plugins.py

Code: Alles auswählen

import gedit

plugins = []

if __name__ == '__main__':
	__import__('myplugin')
	for plugin in gedit.Plugin.__subclasses__():
		plugins.append(plugin())
	for plugin in plugins:
		plugin.activate()
Jan-Nik
User
Beiträge: 5
Registriert: Sonntag 1. April 2007, 13:42
Kontaktdaten:

Dienstag 14. August 2007, 20:08

Eine Sache fällt mir gerade noch auf: Wie kriege ich es hin, dass das Plugin gedit.py importieren kann, ohne dass diese im selben Ordner liegen muss? Und am besten auch so, dass es nicht ein Modul wird, welches nun alle Python-Programme benutzen können.
Hat da jemand einen Tipp für mich?
Benutzeravatar
mq
User
Beiträge: 124
Registriert: Samstag 1. Januar 2005, 19:14

Mittwoch 15. August 2007, 00:34

Kopier den Kram in ein Verzeichnis, in dem Python standardmaessig nach Extension-Modulen sucht (Umgebungsvariable PYTHONPATH, der Standard-Weg ist, den Kram in den Unterordner site-packages des Library-Ordners deiner Python-Installation zu legen).
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 18. August 2007, 22:31

lumax hat geschrieben:Kopier den Kram in ein Verzeichnis, in dem Python standardmaessig nach Extension-Modulen sucht (Umgebungsvariable PYTHONPATH, der Standard-Weg ist, den Kram in den Unterordner site-packages des Library-Ordners deiner Python-Installation zu legen).
Das ist ja eben das, was Jan-Nik nicht wollte.

Entweder kannst du sys.path um den Ordner in dem das Modul liegt erweitern, bevor du es importierst oder du benutzt die in Python 2.5 eingeführten relativen Importanweisungen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Montag 20. August 2007, 11:15

Man kann auch in einem Ordner, der für das Importieren bereits durchsucht wird, eine Datei mit der Endung 'pth', die zu importierende Pfade enthält, erstellen. Ich habe z.B. in den Ordner 'C:\Programme\Python24' eine Datei 'MyScripts.pth' gelegt, die Pfade zu meinen eigenen Modulen, die importiert werden sollen, enthält.
MfG
HWK
Antworten