J'ai une application, écrite en Python, qui est utilisée par un public assez technique (scientifiques).
Je recherche un bon moyen de rendre l'application extensible par les utilisateurs, c'est à dire une architecture de script / plugin.
Je recherche quelque chose d' extrêmement léger . La plupart des scripts, ou plugins, ne seront pas développés et distribués par un tiers et installés, mais seront quelque chose de fouetté par un utilisateur en quelques minutes pour automatiser une tâche répétitive, ajouter la prise en charge d'un format de fichier, etc. Ainsi, les plugins doivent avoir le code standard minimum absolu et ne nécessitent aucune 'installation' autre que la copie dans un dossier (donc quelque chose comme les points d'entrée setuptools, ou l'architecture du plugin Zope semble trop.)
Existe-t-il déjà des systèmes comme celui-ci, ou des projets mettant en œuvre un schéma similaire que je devrais rechercher pour des idées / inspiration?
imp
module est obsolète au profit duimportlib
démarrage de python 3.4imp.load_module
.module_example.py
:loader.py
:C'est certainement "minimal", il n'a absolument aucune vérification d'erreur, probablement d'innombrables problèmes de sécurité, ce n'est pas très flexible - mais cela devrait vous montrer à quel point un système de plugins en Python peut être simple.
Vous voulez probablement regarder dans le diablotin module de trop, mais vous pouvez faire beaucoup avec juste
__import__
,os.listdir
et une manipulation de chaînes.la source
def call_plugin(name, *args)
pourdef call_plugin(name, *args, **kwargs)
, puisplugin.plugin_main(*args)
pourplugin.plugin_main(*args, **kwargs)
imp
est obsolète en faveur deimportlib
Jetez un œil à cet aperçu des frameworks / bibliothèques de plugins existants , c'est un bon point de départ. J'aime assez Yapsy , mais cela dépend de votre cas d'utilisation.
la source
Bien que cette question soit vraiment intéressante, je pense qu'il est assez difficile de répondre, sans plus de détails. De quel genre d'application s'agit-il? At-il une interface graphique? Est-ce un outil de ligne de commande? Un ensemble de scripts? Un programme avec un point d'entrée unique, etc ...
Compte tenu du peu d'informations dont je dispose, je répondrai de manière très générique.
Quels moyens avez-vous pour ajouter des plugins?
Dans le cadre d'une pratique de code / conception pure, vous devrez déterminer clairement le comportement / les actions spécifiques que vous souhaitez que vos utilisateurs étendent. Identifiez le point d'entrée commun / un ensemble de fonctionnalités qui seront toujours remplacées et déterminez les groupes au sein de ces actions. Une fois cela fait, il devrait être facile d'étendre votre application,
Exemple utilisant des hooks , inspiré de MediaWiki (PHP, mais le langage compte-t-il vraiment?):
Un autre exemple, inspiré de mercurial. Ici, les extensions ajoutent uniquement des commandes à l' exécutable de ligne de commande hg , étendant le comportement.
Pour les deux approches, vous aurez peut-être besoin d'une initialisation et d'une finalisation communes pour votre extension. Vous pouvez soit utiliser une interface commune que toute votre extension devra implémenter (correspond mieux à la deuxième approche; mercurial utilise un reposetup (ui, repo) qui est appelé pour toutes les extensions), soit utiliser une approche de type crochet, avec un hooks.setup hook.
Mais encore une fois, si vous voulez des réponses plus utiles, vous devrez affiner votre question;)
la source
Le framework de plugins simple de Marty Allchin est la base que j'utilise pour mes propres besoins. Je recommande vraiment d'y jeter un œil, je pense que c'est vraiment un bon début si vous voulez quelque chose de simple et facilement piratable. Vous pouvez également le trouver sous forme d'extraits de code Django .
la source
Je suis un biologiste à la retraite qui a travaillé avec des micrograqphes numériques et s'est retrouvé à devoir écrire un package de traitement et d'analyse d'images (pas techniquement une bibliothèque) pour fonctionner sur une machine SGi. J'ai écrit le code en C et utilisé Tcl pour le langage de script. L'interface graphique, telle qu'elle était, a été réalisée en utilisant Tk. Les commandes qui apparaissaient dans Tcl étaient de la forme "extensionName commandName arg0 arg1 ... param0 param1 ...", c'est-à-dire de simples mots et nombres séparés par des espaces. Lorsque Tcl a vu la sous-chaîne "extensionName", le contrôle a été passé au package C. Cela a à son tour exécuté la commande via un lexer / parser (fait dans lex / yacc), puis appelé les routines C si nécessaire.
Les commandes pour faire fonctionner le paquet pouvaient être exécutées une par une via une fenêtre dans l'interface graphique, mais les travaux par lots étaient effectués en éditant des fichiers texte qui étaient des scripts Tcl valides; vous choisiriez le modèle qui a fait le type d'opération au niveau du fichier que vous vouliez faire, puis éditeriez une copie pour contenir le répertoire et les noms de fichier réels ainsi que les commandes du package. Ça a marché comme sur des roulettes. Jusqu'à ce que ...
1) Le monde s'est tourné vers les PC et 2) les scripts ont dépassé environ 500 lignes, lorsque les capacités organisationnelles douteuses de Tcl ont commencé à devenir un réel inconvénient. Le temps s'est écoulé ...
J'ai pris ma retraite, Python a été inventé, et il ressemblait au successeur parfait de Tcl. Maintenant, je n'ai jamais fait le portage, car je n'ai jamais affronté les défis de compiler des (assez gros) programmes C sur un PC, d'étendre Python avec un package C et de faire des interfaces graphiques en Python / Gt? / Tk? /? ?. Cependant, la vieille idée d'avoir des scripts de modèle modifiables semble toujours réalisable. En outre, il ne devrait pas être trop lourd d'entrer des commandes de package sous une forme native Python, par exemple:
packageName.command (arg0, arg1, ..., param0, param1, ...)
Quelques points, parens et virgules supplémentaires, mais ce ne sont pas des bouchons.
Je me souviens avoir vu que quelqu'un a fait des versions de lex et yacc en Python (essayez: http://www.dabeaz.com/ply/ ), donc si elles sont encore nécessaires, elles sont là.
Le but de cette randonnée est qu'il m'a semblé que Python lui-même EST le frontal "léger" désiré et utilisable par les scientifiques. Je suis curieux de savoir pourquoi vous pensez que ce n'est pas le cas, et je le pense sérieusement.
ajouté plus tard: l'application gedit anticipe l'ajout de plugins et leur site contient l'explication la plus claire d'une procédure de plugin simple que j'ai trouvée en quelques minutes de recherche. Essayer:
https://wiki.gnome.org/Apps/Gedit/PythonPluginHowToOld
J'aimerais quand même mieux comprendre votre question. Je ne sais pas si vous 1) voulez que les scientifiques puissent utiliser votre application (Python) tout simplement de différentes manières ou 2) souhaitez permettre aux scientifiques d'ajouter de nouvelles fonctionnalités à votre application. Le choix n ° 1 est la situation à laquelle nous avons été confrontés avec les images et qui nous a conduit à utiliser des scripts génériques que nous avons modifiés en fonction des besoins du moment. Est-ce le choix n ° 2 qui vous amène à l'idée de plugins, ou est-ce un aspect de votre application qui rend impossible l'envoi de commandes?
la source
Lorsque je recherche des décorateurs Python, j'ai trouvé un extrait de code simple mais utile. Cela peut ne pas correspondre à vos besoins mais très inspirant.
Système d'enregistrement de plug-in Scipy Advanced Python #
Usage:
la source
WordProcessor.plugin
ne retourne rien (None
), donc importer laCleanMdashesExtension
classe plus tard simplement importeNone
. Si les classes de plugin sont utiles en elles-mêmes, créez la.plugin
méthode de classereturn plugin
.J'ai apprécié la belle discussion sur les différentes architectures de plugins donnée par le Dr André Roberge à Pycon 2009. Il donne un bon aperçu des différentes façons d'implémenter des plugins, en partant de quelque chose de vraiment simple.
Il est disponible sous forme de podcast (deuxième partie après une explication du patching de singe) accompagné d'une série de six entrées de blog .
Je recommande de l'écouter rapidement avant de prendre une décision.
la source
Je suis arrivé ici à la recherche d'une architecture de plugin minimale et j'ai trouvé beaucoup de choses qui me semblaient toutes exagérées. J'ai donc implémenté des plugins Python Super Simple . Pour l'utiliser, vous créez un ou plusieurs répertoires et déposez un
__init__.py
fichier spécial dans chacun d'eux. L'importation de ces répertoires entraînera le chargement de tous les autres fichiers Python en tant que sous-modules, et leur (s) nom (s) seront placés dans la__all__
liste. Ensuite, c'est à vous de valider / initialiser / enregistrer ces modules. Il y a un exemple dans le fichier README.la source
En fait, setuptools fonctionne avec un "répertoire plugins", comme l'exemple suivant tiré de la documentation du projet: http://peak.telecommunity.com/DevCenter/PkgResources#locating-plugins
Exemple d'utilisation:
À long terme, setuptools est un choix beaucoup plus sûr car il peut charger des plugins sans conflits ni exigences manquantes.
Un autre avantage est que les plugins eux-mêmes peuvent être étendus en utilisant le même mécanisme, sans que les applications d'origine aient à s'en soucier.
la source
Comme une autre approche du système de plugins, vous pouvez vérifier le projet Extend Me .
Par exemple, définissons une classe simple et son extension
Et essayez de l'utiliser:
Et montrez ce qui se cache derrière la scène:
La bibliothèque extend_me manipule le processus de création de classe via des métaclasses, ainsi dans l'exemple ci-dessus, lors de la création d'une nouvelle instance de,
MyCoolClass
nous avons une instance de nouvelle classe qui est une sous-classe des deuxMyCoolClassExtension
et quiMyCoolClass
possède la fonctionnalité des deux, grâce à l' héritage multiple de PythonPour un meilleur contrôle sur la création de classe, il y a quelques métaclasses définies dans cette bibliothèque:
ExtensibleType
- permet une extensibilité simple par sous-classementExtensibleByHashType
- similaire à ExtensibleType, mais ayant la capacité de créer des versions spécialisées de la classe, permettant l'extension globale de la classe de base et l'extension des versions spécialisées de la classeCette bibliothèque est utilisée dans OpenERP Proxy Project , et semble fonctionner assez bien!
Pour un exemple réel d'utilisation, regardez dans l'extension 'field_datetime' d'OpenERP Proxy :
Record
voici un objet extensible.RecordDateTime
est l'extension.Pour activer l'extension, importez simplement le module contenant la classe d'extension et (dans le cas ci-dessus)
Record
objets créés après avoir une classe d'extension dans les classes de base, ayant ainsi toutes ses fonctionnalités.Le principal avantage de cette bibliothèque est que le code qui exploite des objets extensibles n'a pas besoin de connaître l'extension et les extensions pourraient tout changer dans les objets extensibles.
la source
my_cool_obj = MyCoolClassExtension1()
au lieu demy_cool_obj = MyCoolClass()
__new__
méthode surchargée , donc elle trouve automatiquement toutes les sous-classes, et construit une nouvelle classe, c'est-à-dire une sous-classe de toutes, et retourne une nouvelle instance de cette classe créée. Ainsi, l'application d'origine n'a pas besoin de connaître toutes les extensions. cette approche est utile lors de la construction de la bibliothèque, pour permettre à l'utilisateur final de modifier ou d'étendre son comportement facilement. dans l'exemple ci-dessus, MyCoolClass peut être défini dans la bibliothèque et utilisé par celle-ci, et MyCoolClassExtension peut être défini par l'utilisateur final.setuptools a un EntryPoint :
AFAIK ce package est toujours disponible si vous utilisez pip ou virtualenv.
la source
Pour développer la réponse de @ edomaur, je suggère de jeter un coup d'œil à simple_plugins (plug sans vergogne), qui est un simple framework de plugin inspiré du travail de Marty Alchin .
Un court exemple d'utilisation basé sur le README du projet:
la source
J'ai passé du temps à lire ce fil pendant que je cherchais un framework de plugin en Python de temps en temps. J'en ai utilisé mais il y avait des lacunes avec eux. Voici ce que je propose pour votre examen en 2017, un système de gestion de plugins sans interface et faiblement couplé: Chargez-moi plus tard . Voici des tutoriels sur son utilisation.
la source
Vous pouvez utiliser pluginlib .
Les plugins sont faciles à créer et peuvent être chargés à partir d'autres packages, chemins de fichiers ou points d'entrée.
Créez une classe parent de plugin, définissant toutes les méthodes requises:
Créez un plugin en héritant d'une classe parent:
Chargez les plugins:
la source
foo
, vous pouvez avoir un module appeléfoo.parents
où vous définissez les classes parentes. Ensuite, vos plugins seraient importésfoo.parents
. Cela fonctionne bien pour la plupart des cas d'utilisation. Parce que 'foo' lui-même est également importé, pour éviter la possibilité d'importations circulaires, de nombreux projets laissent la racine du module vide et utilisent un__main__.py
fichier ou des points d'entrée pour lancer l'application.J'ai passé beaucoup de temps à essayer de trouver un petit système de plugins pour Python, qui répondrait à mes besoins. Mais alors j'ai juste pensé, s'il y a déjà un héritage, qui est naturel et flexible, pourquoi ne pas l'utiliser.
Le seul problème avec l'utilisation de l'héritage pour les plugins est que vous ne savez pas quelles sont les classes de plugins les plus spécifiques (les plus basses de l'arbre d'héritage).
Mais cela pourrait être résolu avec la métaclasse, qui garde la trace de l'héritage de la classe de base, et pourrait éventuellement créer une classe, qui hérite de la plupart des plugins spécifiques ('Root extended' sur la figure ci-dessous)
Je suis donc venu avec une solution en codant une telle métaclasse:
Ainsi, lorsque vous avez une base racine, faite avec une métaclasse, et que vous avez un arbre de plugins qui en héritent, vous pouvez automatiquement obtenir la classe, qui hérite des plugins les plus spécifiques en sous-classant simplement:
La base de code est assez petite (~ 30 lignes de code pur) et aussi flexible que l'héritage le permet.
Si vous êtes intéressé, impliquez-vous @ https://github.com/thodnev/pluginlib
la source
Vous pouvez également consulter Groundwork .
L'idée est de construire des applications autour de composants réutilisables, appelés patterns et plugins. Les plugins sont des classes qui dérivent de
GwBasePattern
. Voici un exemple de base:Il existe également des modèles plus avancés pour gérer, par exemple, les interfaces de ligne de commande, la signalisation ou les objets partagés.
Groundwork trouve ses plugins soit en les liant par programme à une application comme indiqué ci-dessus, soit automatiquement via
setuptools
. Les packages Python contenant des plugins doivent les déclarer en utilisant un point d'entrée spécialgroundwork.plugin
.Voici les documents .
Avertissement : je suis l'un des auteurs de Groundwork.
la source
Dans notre produit de santé actuel, nous avons une architecture de plugin implémentée avec une classe d'interface. Notre pile technologique est Django au-dessus de Python pour l'API et Nuxtjs au-dessus de nodejs pour le frontend.
Nous avons une application de gestionnaire de plugins écrite pour notre produit qui est essentiellement un package pip et npm en conformité avec Django et Nuxtjs.
Pour le développement de nouveaux plugins (pip et npm), nous avons fait du gestionnaire de plugins une dépendance.
Dans le package Pip: Avec l'aide de setup.py, vous pouvez ajouter un point d'entrée du plugin pour faire quelque chose avec le gestionnaire de plugin (registre, initiations, ... etc.) Https://setuptools.readthedocs.io/en/latest/setuptools .html # création-de-script-automatique
Dans le package npm: Similaire à pip, il existe des hooks dans les scripts npm pour gérer l'installation. https://docs.npmjs.com/misc/scripts
Notre cas d'utilisation:
L'équipe de développement de plugins est désormais séparée de l'équipe de développement principale. La portée du développement de plugins est pour l'intégration avec des applications tierces qui sont définies dans l'une des catégories du produit. Les interfaces de plugin sont classées par exemple pour: - Le gestionnaire de plugin de fax, téléphone, email ... etc peut être amélioré à de nouvelles catégories.
Dans votre cas: Peut-être que vous pouvez avoir un plugin écrit et le réutiliser pour faire des choses.
Si les développeurs de plugins ont besoin d'utiliser des objets de base de réutilisation, cet objet peut être utilisé en faisant un niveau d'abstraction dans le gestionnaire de plugins afin que tous les plugins puissent hériter de ces méthodes.
Le simple fait de partager comment nous avons mis en œuvre notre produit espère que cela vous donnera une petite idée.
la source