2009-08-28 6 views
5

コマンドラインオプションを使用してかなり大量の作業を行う管理スクリプトを開発しています。スクリプトの最初の数回の反復では、optparseを使用してユーザーの入力を収集し、ページを実行し、各オプションの値を適切な順序でテストし、必要に応じてアクションを実行しました。これは、コードを読むことと維持することが本当に難しいジャングルを招いています。イントロスペクションを介してコマンドライン引数を解析する

私はより良いものを探しています。

私は多かれ少なかれ普通のPythonの方法で関数を書くことができますし、スクリプトが実行されると、私の関数から生成されたオプション(とヘルプテキスト)を解析して実行します適切な順序。また、私は本当に

は、私がsimon willison's optfunc見つけた場所myscript.py install作品完全に分離myscript.py remove(別のオプション、ヘルプなど)から、ジャンゴ・スタイルサブコマンドインタフェースを構築できるようにしたいのですが、それは多くのことを行います私はオプションを巨大な文字列に圧縮しようとするのではなく、OPTIONを関数として記述したいと思っています。

私は、主要な機能のためのクラスのセットと、コマンドラインの特定のオプションに対応するクラスのそれぞれの定義されたメソッドを含むアーキテクチャを想像してください。この構造は、各オプションを変更する機能コードの近くに配置して保守を容易にするという利点があります。クラスメソッドの順序付けが決定的ではないので、私が対処する方法がわからないのは、コマンドの順序です。

私は車輪を改革する前に:同様に動作する他の既存のコードはありますか?変更が容易な他のものはありますか?質問をすることで、何がいいのか自分の考えが明確になったのですが、なぜこれがひどいアイデアであるのか、それがうまくいかなければならないかというフィードバックは歓迎されます。

答えて

4

「イントロスペクション」で時間を無駄にしないでください。

各「コマンド」または「オプション」は、2組のメソッド関数または属性を持つオブジェクトです。

  1. optparseの設定情報を提供します。

  2. 実際に作業してください。

ここであなたがInstallRemoveためsublcasses、あなたが必要とする他のすべてのコマンドを作成するすべてのコマンド

class Command(object): 
    name= "name" 
    def setup_opts(self, parser): 
     """Add any options to the parser that this command needs.""" 
     pass 
    def execute(self, context, options, args): 
     """Execute the command in some application context with some options and args.""" 
     raise NotImplemented 

のスーパークラスです。

全体的なアプリケーションは次のようになります。

commands = [ 
    Install(), 
    Remove(), 
] 
def main(): 
    parser= optparse.OptionParser() 
    for c in commands: 
     c.setup_opts(parser) 
    options, args = parser.parse() 
    command= None 
    for c in commands: 
     if c.name.startswith(args[0].lower()): 
      command= c 
      break 
    if command: 
     status= command.execute(context, options, args[1:]) 
    else: 
     logger.error("Command %r is unknown", args[0]) 
     status= 2 
    sys.exit(status) 
+0

ありがとう、これは良いアドバイスのようです。 –

+0

これは素晴らしいです! –

0

あなたがやりたいこと、または少なくともあなたのイントロスペクションを自分で行う方法のヒントを与える可能性がありManagement Script Utilitiesを提供WERKZEUG WSGIライブラリ。

次のヘルプメッセージを生成します
from werkzeug import script 

# actions go here 
def action_test(): 
    "sample with no args" 
    pass 

def action_foo(name=2, value="test"): 
    "do some foo" 
    pass 

if __name__ == '__main__': 
    script.run() 

$ python /tmp/test.py --help 
usage: test.py <action> [<options>] 
     test.py --help 

actions: 
    foo: 
    do some foo 

    --name      integer 2 
    --value      string test 

    test: 
    sample with no args 

アクションは、すべての引数がデフォルトを持っている引数の数をとり、「action_」で始まる同じモジュール内の関数です。デフォルト値の型は、引数の型を指定します。

引数は、位置によって渡すことも、--name = valueをシェルから渡すこともできます。

関連する問題