Frage

Es gibt mehrere Dienstprogramme - alle mit unterschiedlichen Verfahren, Einschränkungen und Zielbetriebssysteme - für die Zeugung eines Python-Paket und alle seine Abhängigkeiten und sie zu einem einzigen binären Programm drehen, die an die Kunden Schiff ist einfach:

Meine Situation geht noch einen Schritt weiter: Drittanbieter-Entwickler zu schreiben Plug-In, Erweiterungen fehlen, oder Add-ons für meine Anwendung. Es ist natürlich eine schwierige Frage, wie die Nutzer auf Plattformen wie Windows wäre am einfachsten Plug-Ins oder Add-ons in einer solchen Art und Weise installieren, dass meine App kann leicht feststellen, dass sie installiert wurden. Aber jenseits dieser grundlegenden Frage ist eine andere: Wie kann ein Drittanbieter-Entwickler Bündel ihre Erweiterung mit dem, was Bibliotheken die Erweiterung selbst benötigt (die Binärmodule sein könnte, wie lxml) derart, dass das Plugin-Abhängigkeiten für den Import in der gleichen zur Verfügung stehen Zeit, dass das Plugin zur Verfügung steht.

Wie kann das angegangen werden? Wird meine Bewerbung müssen ihre eigenen Plug-in-Bereich auf der Festplatte und einem eigenen Plug-in-Registrierung diese lenkbar machen? Oder gibt es allgemeine Mechanismen, dass ich mich zu schreiben vermeiden könnte, wäre eine App erlauben, die als eine einzige ausführbare Datei verteilt suchen um und finden Sie Plugins, die auch als einzelne Dateien installiert sind?

War es hilfreich?

Lösung

Sie sollten Lage sein, ein Plugin-Verzeichnis haben, dass Ihre Anwendung zur Laufzeit überprüft (oder höher), um den Code in Frage zu importieren. Hier ist ein Beispiel, das mit regelmäßigen Py oder .pyc Code, dass auch Arbeiten mit Plugins gespeichert in ZIP-Dateien (so dass Benutzer nur someplugin.zip im ‚Plug-in‘ fallen könnten Verzeichnis und haben es auf magische Arbeit) funktionieren soll:

import re, os, sys
class Plugin(object):
    """
    The base class from which all plugins are derived.  It is used by the
    plugin loading functions to find all the installed plugins.
    """
    def __init__(self, foo):
        self.foo = foo
    # Any useful base plugin methods would go in here.

def get_plugins(plugin_dir):
    """Adds plugins to sys.path and returns them as a list"""

    registered_plugins = []

    #check to see if a plugins directory exists and add any found plugins
    # (even if they're zipped)
    if os.path.exists(plugin_dir):
        plugins = os.listdir(plugin_dir)
        pattern = ".py$"
        for plugin in plugins:
            plugin_path = os.path.join(plugin_dir, plugin)
            if os.path.splitext(plugin)[1] == ".zip":
                sys.path.append(plugin_path)
                (plugin, ext) = os.path.splitext(plugin) # Get rid of the .zip extension
                registered_plugins.append(plugin)
            elif plugin != "__init__.py":
                if re.search(pattern, plugin):
                    (shortname, ext) = os.path.splitext(plugin)
                    registered_plugins.append(shortname)
            if os.path.isdir(plugin_path):
                plugins = os.listdir(plugin_path)
                for plugin in plugins:
                    if plugin != "__init__.py":
                        if re.search(pattern, plugin):
                            (shortname, ext) = os.path.splitext(plugin)
                            sys.path.append(plugin_path)
                            registered_plugins.append(shortname)
    return registered_plugins

def init_plugin_system(cfg):
    """
    Initializes the plugin system by appending all plugins into sys.path and
    then using load_plugins() to import them.

        cfg - A dictionary with two keys:
        plugin_path - path to the plugin directory (e.g. 'plugins')
        plugins - List of plugin names to import (e.g. ['foo', 'bar'])
    """
    if not cfg['plugin_path'] in sys.path:
        sys.path.insert(0, cfg['plugin_path'])
    load_plugins(cfg['plugins'])

def load_plugins(plugins):
    """
    Imports all plugins given a list.
    Note:  Assumes they're all in sys.path.
    """
    for plugin in plugins:
        __import__(plugin, None, None, [''])
        if plugin not in Plugin.__subclasses__():
            # This takes care of importing zipped plugins:
            __import__(plugin, None, None, [plugin])

So kann sagen, ich habe ein Plugin namens „foo.py“ in einem Verzeichnis ‚Plugins‘ genannt (die im Basisverzeichnis meiner app ist), die eine neue Fähigkeit zu meiner Anwendung hinzufügen. Der Inhalt könnte wie folgt aussehen:

from plugin_stuff import Plugin

class Foo(Plugin):
    """An example plugin."""
    self.menu_entry = {'Tools': {'Foo': self.bar}}
    def bar(self):
        return "foo plugin!"

Ich konnte meinen Plugins initialisieren, wenn ich meine app wie so starten:

plugin_dir = "%s/plugins" % os.getcwd()
plugin_list = get_plugins(plugin_dir)
init_plugin_system({'plugin_path': plugin_dir, 'plugins': plugin_list})
plugins = find_plugins()
plugin_menu_entries = []
for plugin in plugins:
    print "Enabling plugin: %s" % plugin.__name__
    plugin_menu_entries.append(plugin.menu_entry))
add_menu_entries(plugin_menu_entries) # This is an imaginary function

Das sollte funktionieren, solange das Plugin ist entweder ein Py oder .pyc Datei (vorausgesetzt, es ist Byte-kompiliert für die Plattform in Frage). Es kann eigenständige Datei oder innerhalb eines Verzeichnisses sein mit einem init Py oder innerhalb einer Zip-Datei mit den gleichen Regeln.

Wie kann ich wissen, das funktioniert? Es ist, wie ich implementiert Plugins in PyCI . PyCI ist eine Web-Anwendung, aber es gibt keinen Grund, warum diese Methode nicht funktionieren würde für eine GUI ‚regelmäßige ol. Für das obige Beispiel wähle ich eine imaginäre add_menu_entries () Funktion in Verbindung mit einem Plugin-Objektvariable zu verwenden, die verwendet werden könnten, ein Plugin Methode auf Ihren GUI Menüs hinzuzufügen.

Hoffentlich diese Antwort wird Ihnen helfen, Ihr eigenes Plugin-System aufzubauen. Wenn Sie genau sehen wollen, wie es umgesetzt wird, empfehle ich Ihnen die PyCI Quellcode und Blick auf plugin_utils.py herunterladen und die Beispiel-Plug-in plugins_enabled Verzeichnis.

Andere Tipps

Hier ist ein weiteres Beispiel für einen Python-App, dass Hilfe von Plugins: OpenSTV . Dabei können die Plugins nur Python-Module sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top