ホットスワップPythonコード(アヒル型関数?)
-
26-09-2019 - |
質問
私はこれについてあまりにも長い間考えてきましたが、何もアイデアが得られませんでした。もしかしたら、あなたの何人かが助けてくれるかもしれません。
Python スクリプトのフォルダーがあり、その周囲の本体はすべて同じです (文字通り、シェル スクリプトから生成した) が、すべてとは異なるチャンクが 1 つあります。言い換えると:
Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)
そして今日、これは悪い考えだと気付きました。たとえば、上部または下部のセクションから何かを変更したい場合は、それを行うためのシェル スクリプトを作成する必要があります。(それが難しいというわけではありません。コード的に非常に悪いように思えるだけです)。
そこで、私がやりたいのは、次のような外側の Python スクリプトを 1 つ用意することです。
Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code
そして、フォルダー内の他のすべての Python ファイルは、単にコードの中間部分になる可能性があります。ただし、通常のモジュールはここでは機能しません(私が間違っていない限り)。実行する必要があるコードを引数から取得するため、それは文字列になるため、実行時までどの関数を実行するかわかりません。 。
そこで、さらに 2 つの解決策を考えました。
- 特定のパラメーターに基づいて各スクリプトを実行するための if ステートメントを大量に作成できます。以前のデザインよりもさらに悪いので、これを拒否しました。
使用できます:
os.command(sys.argv[0] scriptName.py)
これでスクリプトが実行されますが、Python を呼び出すために Python を呼び出すのは、私にはあまりエレガントとは思えません。
それで、他に何かアイデアがある人はいますか?ありがとう。
解決
あなたは、文字列としての機能や、文字列としてモジュールの名前の名前を知っている場合は、あなたが行うことができます。
mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()
他のヒント
もう1つの可能な解決策は、あなたの繰り返しの各ファイルは、メインファイルから機能をインポートすることです。
from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
すでに投稿されているいくつかの回答に加えて、次のことを考慮してください。 テンプレートメソッド デザインパターン:次のような抽象クラスを作成します
class Base(object):
def top(self): ...
def bottom(self): ...
def middle(self): raise NotImplementedError
def doit(self):
self.top()
self.middle()
self.bottom()
すべてのプラグ可能モジュールは、これを継承するクラスを作成します。 Base
そしてオーバーライドする必要があります middle
関連するコードを付けます。
おそらく、この単純なケースでは保証されません (クラスをインスタンス化して呼び出しするには、適切なモジュールをインポートする必要があります) doit
ただし、「プラグイン可能な部分」の数や複雑さが増加し続ける場合に備えて、(多くの Python のバリエーションとともに、YouTube で公開されている多くの技術講演で十分に説明しています) 覚えておく価値はあります -- テンプレート メソッド(その恐ろしい名前にもかかわらず;-) は、しっかりとした、十分に実証された、拡張性の高いパターンです [[時には少し厳格すぎるかもしれませんが、それはまさに私がこれらの多くの技術的な講演で取り上げていることです -- そしてその問題はこの特定のパターンには当てはまりません使用事例]]。
しかし、通常のモジュールは、(私が間違えてる場合を除き)私は、コードになるだろうので、私は文字列になりarguement、から実行する必要がここに働かないので、私は知らないであろう機能に実行時まで実行します。
それだけで正常に動作します - 使用 __import__
の組み込みをか、あなたの場合スクリプトをインポートするには、 IMP のモジュールは非常に複雑なレイアウトを持っています。そして、あなたは、たとえばmodule.__dict__[funcname]
によって機能を得ることができます。
(他の回答で説明したように)モジュールをインポートすると、間違いなくこれを行うためのクリーンな方法ですが、限り、あなたはあなたが使用することができますあまりにも変なもの<のhrefをやっていないとして、仕事をしません何らかの理由であれば= "http://docs.python.org/py3k/library/functions.html#exec" のrel = "nofollowをnoreferrer"> exec
を。それはexec
が呼び出された時点で、現在のファイルに含まれているかのように、それは基本的に別のファイルの内容を実行します。それは多くのシェルに含ま種類のsource
ステートメントにPythonが持っている最も近いものです。最低限として、このような何か作業をする必要があります:
exec(open(filename).read(None))
これはどう?
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