2017-05-30 19 views
0

ユーザーが任意の数のサンプルを宣言できるコマンドラインインターフェイスをサポートしたいと思います。各サンプルに対応する1つ以上の入力ファイルがあります。このような何か:Pythonで関連する名前付き引数の任意の数をサポートするargparse

$ myprogram.py \ 
     --foo bar \ 
     --sample1 input1.tsv \ 
     --sample2 input2a.tsv input2b.tsv input2c.tsv \ 
     --sample3 input3-filtered.tsv \ 
     --out output.tsv 

アイデアは、オプションキーがパターン--sample(\d+)に一致することで、次の-または--プレフィックスフラグに遭遇するまで、各キーはオプションの値として、後続のすべての引数を消費します。明示的に宣言された引数の場合、これは​​モジュールがnargs='+'オプションでサポートする一般的な使用例です。しかし、私は任意の数の引数をサポートする必要があるため、明示的に宣言することはできません。

parse_known_argsコマンドを使用すると、ユーザーが指定したすべての引数にアクセスできますが、明示的に宣言されていない引数はインデックス付きのデータ構造にグループ化されません。これらについては、引数リストを慎重に調べ、現在のフラグなどに対応する後続の値の数を調べる必要があります。

本質的に再実装することなくこれらのオプションを解析する方法はありますか引数パーサーの大部分(ほとんど)がゼロからですか?

+0

あなたはその場でargparserを構築すると考えましたか?コマンドラインで '--sample'の数を数え、それを使って適切なargparserをビルドします。ラウンドアバウトの種類ですが、それはargparseが重い持ち上げを行うことができます。 – TemporalWolf

答えて

1

$ myprogram.py \ 
    --foo bar \ 
    --sample input1.tsv \ 
    --sample input2a.tsv input2b.tsv input2c.tsv \ 
    --sample input3-filtered.tsv \ 
    --out output.tsv 

パラメータ名は番号が含まれていませんが、それでも、それはグループ分けを行い、これを試してみてください。

parser.add_argument('--sample', action='append', nargs='+') 

これは、リストのリストを生成する。--sample x y --sample 1 2私は私のコメントで述べたようにNamespace(sample=[['x', 'y'], ['1', '2']])

+0

私は前に 'action =" append "'を使用しましたが、この文脈では決して使用しませんでした。素晴らしい提案! –

0

​​ではなく、clickで探していることをやり遂げることができます。

引用すると:

を$ click_

をクリックして、必要に応じて、わずかコードで構成可能な方法で美しいコマンドライン インタフェースを作成するためのPythonパッケージです。 「コマンドラインインターフェイス作成キット」です。それは高度に ですが、デフォルトの妥当なデフォルトを備えています。

は、意図したCLI APIを実装できないことによって引き起こされる不満を防ぎながら、コマンドラインツールを迅速に作成することを目的としています。三点で

クリック:

コマンド
  • 自動ヘルプページ生成
  • でドキュメントを読むランタイム

    でサブコマンドの遅延読み込みをサポートしています

  • クリックの重要な特徴の一つは、あなたのようにあなたのコマンドラインを構築できるようにする必要があり、サブコマンドを構築する能力、(ビット秘密の魔法のgitや画像を使用してのように)、次のとおりです。

    myprogram.py \ 
        --foo bar \ 
        --sampleset input1.tsv \ 
        --sampleset input2a.tsv input2b.tsv input2c.tsv \ 
        --sampleset input3-filtered.tsv \ 
        combinesets --out output.tsv 
    

    かさえ:あなたのコードは--fooと呼ばれるパラメータと--outprocesscombineプロセスと呼ばれる機能を持つことになり、この場合には、きれいかもしれない

    myprogram.py \ 
        --foo bar \ 
        process input1.tsv \ 
        process input2a.tsv input2b.tsv input2c.tsv \ 
        process input3-filtered.tsv \ 
        combine --out output.tsv 
    

    は、指定された入力ファイル(複数可)と呼ばれ、ノーパラと結合されるだろうメートル。

    +1

    クリックでこれを行う方法を実際に示すことができない限り、または少なくとも使用する機能を指定することはできませんが、これは本当に答えとしてカウントされません。 – jwodder

    1

    別の引数値でその番号またはキーを作成し、関連する引数をネストされたリストで収集する方が簡単です。

    import argparse 
    
    parser = argparse.ArgumentParser() 
    parser.add_argument('--foo') 
    parser.add_argument('--out') 
    parser.add_argument('--sample', nargs='+', action='append', metavar=('KEY','TSV')) 
    
    parser.print_help() 
    
    argv = "myprogram.py \ 
         --foo bar \ 
         --sample 1 input1.tsv \ 
         --sample 2 input2a.tsv input2b.tsv input2c.tsv \ 
         --sample 3 input3-filtered.tsv \ 
         --out output.tsv" 
    argv = argv.split() 
    args = parser.parse_args(argv[1:]) 
    print(args) 
    

    は生成します。

    1031:~/mypy$ python3 stack44267794.py -h 
    usage: stack44267794.py [-h] [--foo FOO] [--out OUT] [--sample KEY [TSV ...]] 
    
    optional arguments: 
        -h, --help   show this help message and exit 
        --foo FOO 
        --out OUT 
        --sample KEY [TSV ...] 
    Namespace(foo='bar', out='output.tsv', 
        sample=[['1', 'input1.tsv'], 
          ['2', 'input2a.tsv', 'input2b.tsv', 'input2c.tsv'], 
          ['3', 'input3-filtered.tsv']]) 
    

    一般key:valueペアを収集についての質問がありました。それを直接サポートするものは​​にはありません。いろいろなことが示唆されていますが、皆は自分自身でペアを解析することに沸きます。

    Is it possible to use argparse to capture an arbitrary set of optional arguments?

    あなたはキーごとに引数の数が可変である合併症を追加しました。これは ' - sample1 = input1'を単純な文字列として扱うことを排除します。

    ​​は、周知のコマンドライン標準であるPOSIXを拡張しました。しかし、それを超えて移動したい場合は、前に(sys.argv)または​​(parse_known_argsextras)の後に引数を処理する準備をしてください。あなたはすなわち、わずかに異なる構文、一緒に暮らすことができる場合

    1

    を生成します:

    import argparse 
    
    argv = "myprogram.py \ 
         --foo bar \ 
         --sample1 input1.tsv \ 
         --sample2 input2a.tsv input2b.tsv input2c.tsv \ 
         --sample3 input3-filtered.tsv \ 
         --out output.tsv" 
    
    parser = argparse.ArgumentParser() 
    parser.add_argument('--foo') 
    parser.add_argument('--out') 
    for x in range(1, argv.count('--sample') + 1): 
        parser.add_argument('--sample' + str(x), nargs='+') 
    args = parser.parse_args(argv.split()[1:]) 
    

    は与える:リアルsys.argv

    print args 
    Namespace(foo='bar', out='output.tsv', sample1=['input1.tsv'], sample2=['input2a.tsv', 'input2b.tsv', 'input2c.tsv'], sample3=['input3-filtered.tsv']) 
    

    あなたはおそらく少し長く' '.join(sys.argv).count('--sample')

    argv.countを交換する必要があります

    このアプローチの主な欠点は、自動ヘルプの生成です。これらのフィールドはカバーしていません。

    +1

    あなたのコードは文字列 'argv'で動作しますが、すでに分割された' sys.argv'では動作しません。ヘルプは '-h 'と共に、コマンドラインでも与えられた' sample#'をリストします。しかし、一般的な 'sample#'を表示するには、カスタム 'usage'パラメータを使用する必要があります。 – hpaulj

    関連する問題