Hot Swapping Python-Code (Ente Typ Funktionen?)
-
26-09-2019 - |
Frage
Ich habe viel zu lange darüber nachgedacht und haben keine Ahnung bekommen, vielleicht können einige von euch helfen.
Ich habe einen Ordner mit Python-Skripte, die alle den gleichen umgebenden Körper (wörtlich: Ich erzeugen es von einem Shell-Skript), aber einen Brocken habe, als sie alle anders. Mit anderen Worten:
Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)
Und mir heute klar, dass dies eine schlechte Idee ist, zum Beispiel, wenn ich von den oberen oder unteren Abschnitten etwas ändern will, muß ich einen Shell-Skript schreiben, es zu tun. (Nicht, dass das ist schwer, es scheint nur, wie es ist sehr schlecht Code weise).
Also, was ich tun möchte, ist eine äußere Python-Skript, die wie folgt lautet:
Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code
Und dann kann jede andere Python-Datei in dem Ordner einfach das mittlere Stück Code sein. Allerdings würde Normalmodul nicht hier arbeiten (es sei denn, ich irre), weil ich den Code bekommen würde ich von der arguement ausführen müssen, die eine Zeichenfolge sein würde, und so würde ich nicht wissen, welche Funktion erst zur Laufzeit laufen .
dachte Also habe ich zwei weitere Lösungen auf:
- Ich konnte eine Reihe von if-Anweisungen aufzuschreiben, ein jedes Skript ausgeführt werden sollen, basierend auf einem bestimmten Parameter. Ich lehnte dies, wie es ist noch schlimmer als die bisherige Konstruktion.
-
Ich konnte verwenden:
os.command (sys.argv [0] scriptName.py)
, die das Skript ausführen würde, aber auf Anruf Python ruft Python scheint nicht sehr elegant zu mir.
So hat jemand noch andere Ideen? Danke.
Lösung
Wenn Sie den Namen der Funktion als String und dem Namen des Moduls als String kennen, dann können Sie tun,
mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()
Andere Tipps
Ein andere mögliche Lösung ist jede Ihrer wiederholenden Dateien zu haben, um die Funktionalität von der Hauptdatei importieren
from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
Zusätzlich zu den verschiedenen Antworten bereits gebucht, sollten Sie die Template-Methode Design-Muster: macht eine abstrakte Klasse wie
class Base(object):
def top(self): ...
def bottom(self): ...
def middle(self): raise NotImplementedError
def doit(self):
self.top()
self.middle()
self.bottom()
Jedes steckbares Modul macht dann eine Klasse, die erbt von diesem Base
und middle
mit dem entsprechenden Code überschreiben muss.
Vielleicht nicht für diesen einfachen Fall gerechtfertigt (Sie müssen noch das richtige Modul importieren, um seine Klasse und Call doit
darauf zu instanziiert), aber immer noch wert unter Berücksichtigung (zusammen mit seinen vielen Pythonic Variationen, die ich habe reichlich erklärte heute in vielen Tech-Gesprächen auf youtube verfügbar) für Fälle, in denen die Anzahl und Komplexität von „Pluggable Stücken“ weiter wachsen - Template-Methode (trotz seiner schrecklichen Namen ;-) ist ein solides, bewährten und hochskalierbare Muster [[ manchmal ein bisschen zu steif, aber das ist genau das, was ich in den vielen Tech-Gesprächen Adresse - und das Problem gilt nicht auf diesen speziellen Anwendungsfall]]
Allerdings würde Normalmodul nicht hier arbeiten (es sei denn, ich irre), weil ich den Code bekommen würde ich von der arguement ausführen müssen, die eine Zeichenfolge sein würde, und so würde ich weiß nicht, welche Funktion läuft bis zur Laufzeit.
Es wird gut funktionieren - Verwendung __import__
builtin oder, wenn Sie hat sehr komplexes Layout, imp Modul Ihr Skript zu importieren. Und dann können Sie die Funktion von module.__dict__[funcname]
zum Beispiel erhalten.
ein Modul importieren (wie in anderen Antworten erklärt) ist auf jeden Fall der Reiniger Weg, dies zu tun, aber wenn aus irgendeinem Grund nicht funktioniert, solange Sie nicht etwas zu seltsam tun können Sie a href verwenden < = "http://docs.python.org/py3k/library/functions.html#exec" rel = "nofollow noreferrer"> exec
. Es läuft im Grunde den Inhalt einer anderen Datei, als ob es in der aktuellen Datei an dem Punkt aufgenommen wurde, wo exec
genannt wird. Es ist die nächste Sache, Python hat zu einer source
Aussage der Art in vielen Schalen enthalten. Als absolutes Minimum, sollte in etwa so funktionieren:
exec(open(filename).read(None))
Wie wäre das?
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