code python hot swapping (fonctions de type canard?)
-
26-09-2019 - |
Question
J'ai réfléchi à ce sujet beaucoup trop long et n'a pas eu une idée, peut-être certains d'entre vous peut aider.
J'ai un dossier de scripts python, qui ont toutes le même corps environnant (littéralement, je généré à partir d'un script shell), mais avoir un morceau qui est différent de tous. En d'autres termes:
Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)
Et je me suis rendu aujourd'hui que cela est une mauvaise idée, par exemple, si je veux changer quelque chose du haut ou du bas sections, je dois écrire un script shell pour le faire. (Non pas que cela est difficile, il semble tout comme il est un code très mauvais sage).
Alors ce que je veux faire, est avoir un script python externe qui est comme ceci:
Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code
Et puis tous les autres fichiers python dans le dossier peut être simplement la partie centrale du code. Cependant, le module normale ne fonctionnerait pas ici (à moins que je ne me trompe pas), parce que je recevrais le code que je dois exécuter à partir du arguement, ce qui serait une chaîne, et donc je ne sais pas quelle fonction à exécuter avant l'exécution .
Je pensais que jusqu'à deux solutions:
- Je pourrais écrire un tas de déclarations si, un pour exécuter chaque script basé sur un certain paramètre. Je rejetais cela, car il est encore pire que la conception précédente.
-
Je pourrais utiliser:
os.command (sys.argv [0] scriptName.py)
qui exécuter le script, mais appeler python à python d'appel ne semble pas très élégant pour moi.
Quelqu'un at-il d'autres idées? Merci.
La solution
Si vous connaissez le nom de la fonction comme une chaîne et le nom du module comme une chaîne, vous pouvez le faire
mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()
Autres conseils
Une autre solution possible est d'avoir chacun de vos fichiers répétitifs importer la fonctionnalité du fichier principal
from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
En plus des plusieurs réponses déjà affiché, tenez compte le modèle de conception de méthode modèle: faire une classe abstraite comme
class Base(object):
def top(self): ...
def bottom(self): ...
def middle(self): raise NotImplementedError
def doit(self):
self.top()
self.middle()
self.bottom()
Chaque module de connectables fait alors une classe qui hérite de cette Base
et doit passer outre middle
avec le code correspondant.
Peut-être (avez-vous encore faire pour importer le bon module afin d'instancier sa doit
de classe et appel à ce sujet) ne se justifie pas pour ce cas simple, mais toujours utile de garder à l'esprit (avec ses nombreuses variantes pythonique, que j'ai amplement expliqué dans de nombreux pourparlers de technologie maintenant disponible sur YouTube) pour les cas où le nombre ou la complexité des « pièces » connectables ne cesse de croître - Méthode modèle (malgré son nom ;-) est un horrible modèle solide, éprouvé et hautement évolutive [[ parfois un peu trop rigide, mais c'est exactement ce que j'adresse dans les nombreux entretiens tech - et ce problème ne s'applique pas à cette utilisation spécifique cas]]
Cependant, le module normale ne fonctionnerait pas ici (à moins que je ne me trompe pas), parce que je recevrais le code que je dois exécuter à partir du arguement, ce qui serait une chaîne, et donc je ne sais pas quelle fonction courir jusqu'à l'exécution.
Il fonctionne très bien - __import__
ou builtin, si vous ont mise en page très complexe, diablotin module pour importer votre script. Et puis vous pouvez obtenir la fonction par module.__dict__[funcname]
par exemple.
Importer un module (comme expliqué dans d'autres réponses) est certainement la manière propre à faire, mais si pour une raison qui ne fonctionne pas, tant que vous ne rien faire trop bizarre, vous pouvez utiliser exec
. Il fonctionne essentiellement le contenu d'un autre fichier comme si elle était inclus dans le fichier en cours au moment où exec
est appelé. Il est la chose la plus proche Python a une déclaration de source
du genre inclus dans beaucoup de coquilles. Comme un strict minimum, quelque chose comme cela devrait fonctionner:
exec(open(filename).read(None))
Comment cela?
function do_thing_one():
pass
function do_thing_two():
pass
dispatch = { "one" : do_thing_one,
"two" : do_thing_two,
}
# do something to get your string from the command line (optparse, argv, whatever)
# and put it in variable "mystring"
# do top thing
f = dispatch[mystring]
f()
# do bottom thing