5

argparse (または何か他のもの?) を使用して、各位置引数にデフォルト値を持つオプションの引数を持たせたいと思います。

引数は次のようになります。

script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5

そして、これを解析して、位置引数のリストやデフォルトが入力されたオプションの引数のリストなど、使用可能なものに変換したいと考えています。たとえば、上記の例でオプションのデフォルトが 0 の場合:

positional = [arg1, arg2, arg3, arg4, arg5]
optional = [0, 1, 2, 0, 0]

言い換えれば、parser.add_argument('-o', action='append')位置引数を失うため、必要なものではありません。各オプションの引数が関連付けられています。

4

3 に答える 3

3

これは私がまとめた簡単なハックであり、始めるのに妥当な場所かもしれません:

import argparse

class PositionalAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        lst = getattr(namespace,self.dest)
        lst.append(values)
        parser.last_positional_values = lst
        all_positional = getattr(namespace,'all_positional',[])
        all_positional.append(lst)
        namespace.all_positional = all_positional

class AssociateAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        try:
            parser.last_positional_values.append(values)
        except AttributeError:
            pass

parser = argparse.ArgumentParser()
parser.add_argument('-o',action=AssociateAction,dest=argparse.SUPPRESS)
junk,unknown = parser.parse_known_args()

for i,_ in enumerate(unknown):
    parser.add_argument('arg%d'%i,action=PositionalAction,default=[])

print parser.parse_args()

そして、ここでそれが実行されています:

temp $ python test1.py foo -o 1 bar -o 2 baz qux -o 4
Namespace(all_positional=[['foo', '1'], ['bar', '2'], ['baz'], ['qux', '4']], arg0=['foo', '1'], arg1=['bar', '2'], arg2=['baz'], arg3=['qux', '4'])

この問題にはいくつかの課題があります。まず、任意の数の位置引数を受け入れたい - argparse はそれを好まない。argparse は、何を期待するかを事前に知りたがっています。解決策は、パーサーを作成してコマンドラインを解析することですが、既知の引数のみを解析するように argparse に指示することです (この場合、非位置-o引数はすべてサイレントに解析されますが、「位置」引数は解析されません)。 parse_known_argsの形式でタプルを返すため、これに最適です(namespace_of_parsed_stuff, uknown_args)。これで、未知の引数がわかりました。parse_args を満足させるには、パーサーごとに位置引数を追加するだけです。

では、カスタム アクションは実際に何をしているのでしょうか。位置引数が (2 番目のパスで) 見つかった場合、デフォルト (リスト) を取得し、そのリストに値を追加します (以降、「値」リストと呼びます)。次に、「値」リストへの参照を使用してパーサーを変更します。名前空間から「all_positional」リストも取得します。その属性がない場合は、空のリストを取得します。「値」リストを「all_positional」リストに追加し、名前空間に戻します。

ここで、-oフラグをヒットすると、パーサーを調べて「値」リストを取得し、そのリストに追加の値を追加します。パーサーにまったく触れずに同じことを行うことができます...(見ることができますnamespace.all_positional[-1]-それは と同じリストparser.last_positional_valuesです)。

于 2013-01-18T16:15:48.243 に答える
0

自分で sys.argv を単純にステップ実行するのはどうですか。argparse が提供する追加機能は必要ないようです。例えば:

argv='script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5'.split()
pos=[]
opt=[]
i=1
while i<len(argv):
    a=argv[i]
    if a[:2]!='-o':
        pos.append(a)
        opt.append(0)
    else:
        i += 1
        opt[-1]=argv[i]
    i += 1
于 2013-07-28T04:28:19.870 に答える
-1

を使用optparseします。少し複雑な場合は強力です。

op = optparse.OptionParser(usage=usage)

op.add_option('-c','--cmd',dest='cmd',help="""Command to run. Mutually exclusive with -s. You can use string ${ADDR} to have it replaced with specified host address in the command. """)

op.add_option('-s','--script',dest='script',help="""Script file to run remotely. Mutually exclusive with -c. A script can have its own arguments; specify the whole command in doublequotes, like "script -arg arg".""")

op.add_option('-l','--replicate-owner',dest='replicateowner',action="store_true",help="""Replicate (symbolic) owner and (symbolic) group of the file on the remote host, if possible. If remote account with username the same as local account does not exist on remote host, this will silently fail.""")

# parse cmdline options
(opts, args) = op.parse_args()

opts は名前付き引数を取得し、args は位置引数を取得します。

値を取ったり、true または false を設定したり、さらに IIRC を設定したりできる位置引数を指定できます。

于 2013-01-18T16:19:14.463 に答える