Seite 1 von 1

Plugin-System mit Plugin-Basisklasse.

Verfasst: Sonntag 12. August 2007, 17:11
von Jan-Nik
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?

Verfasst: Sonntag 12. August 2007, 17:22
von BlackJack
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.

Verfasst: Sonntag 12. August 2007, 17:50
von Jan-Nik
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()

Verfasst: Dienstag 14. August 2007, 20:08
von Jan-Nik
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?

Verfasst: Mittwoch 15. August 2007, 00:34
von mq
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).

Verfasst: Samstag 18. August 2007, 22:31
von Leonidas
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.

Verfasst: Montag 20. August 2007, 11:15
von HWK
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