0

事前定義された特殊な構文で区切られた可変長の引数リストを解析するにはどうすればよいですか? 例:

   ./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3

スクリプトで解析した後、 、、 のargparse3 つの引数が必要です。引数は、 、、の 3 つの値のリストで構成する必要があります。arg1cmdnamearg3cmdnameotherscripta1a2

cmdnameこのようなレシピがあると、すべてをsubprocess.popen(cmdname, ...)呼び出しに渡すことができるので便利です。

サブパーサーについて考えていました。しかし、サブパーサーを止めることはできず、実際には他のサブパーサーと相互に排他的であると私は信じています。すでに提供されている他の簡単な方法はありますか?サブクラス化はActionそれを行う方法ですか?

4

2 に答える 2

3

--で始まる引数を、同じく で始まるコマンドの部分と区別すると、argparse に役立ちます--

./script ++arg1 ++cmdname otherscript --a1 --a2 ++arg3 が受け入れられる場合は、次のようになります。

import argparse
import shlex

parser = argparse.ArgumentParser(prefix_chars = '+')
parser.add_argument('++arg1', action = 'store_true')
parser.add_argument('++arg3', action = 'store_true')
parser.add_argument('++cmdname', nargs = '*')
args = parser.parse_args(shlex.split("++arg1 ++cmdname otherscript --a1 --a2 ++arg3")) 
print(args)

収量

Namespace(arg1=True, arg3=True, cmdname=['otherscript', '--a1', '--a2'])
于 2012-11-01T13:26:01.517 に答える
2

あなたの投稿で示したように、サブクラス化はおそらくこれを行う方法です - への引数が argparse によって認識されていないAction場合、それはかなりトリッキーになります。otherscriptでこれを回避できるかもparse_known_argsしれませんが、できないかもしれません。正直なところ、最も簡単な方法は自分自身を前処理することだと思いsys.argvます。

import shlex
s = shlex.split("./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3")
def preprocess(lst):
    """
    process an iterable into 2 lists.
    The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
    whereas the first portion contains the rest of it.
    """
    argv1,argv2 = [],[]
    current = argv1
    for i in lst:
        if i == '--cmdname':
           current = argv2
        elif i == '--cmdname--':
           current = argv1
        else:
           current.append(i)
    return argv1,argv2

l1,l2 = preprocess(s)
print l1
print l2

そして、メソッドpreprocessを持つスライス可能なオブジェクトに対して機能する代替実装は、問題なく機能します。.indexsys.argv

def preprocess(lst):
    """
    process an iterable into 2 lists.
    The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
    whereas the first portion contains the rest of it.
    """
    try:
        i1 = lst.index('--cmdname')
        i2 = lst.index('--cmdname--')
        argv1 = lst[i1+1:i2]
        argv2 = lst[:i1]+lst[i2+1:]
    except ValueError:
        argv1 = lst
        argv2 = []

    return argv1,argv2

別のオプション (@unutbu による優れたコメントで指摘されています) は、コマンドライン構文をもう少し標準的なものに変更して、問題を大幅に簡素化することです。

./script --arg1 --cmd "otherscript --a1 --a2" --arg3

cmd次に、通常どおりに解析できargparseます (この引数を指定type=shlex.splitして、文字列から引数のリストに変換します)。

于 2012-11-01T13:08:45.840 に答える