14

私の Python スクリプトでは、別のオプションのパラメーターが指定されている場合にのみ、オプションの入力パラメーターを使用できるようにしたいと考えています。例:

$ python myScript.py --parameter1 value1
$ python myScript.py --parameter1 value1 --parameter2 value2

だがしかし:

$ python myScript.py --parameter2 value2

argparse でこれを行うにはどうすればよいですか?

ありがとう!

4

3 に答える 3

12

カスタム アクションを使用します。

import argparse

foo_default=None    

class BarAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        didfoo=getattr(namespace,'foo',foo_default)
        if(didfoo == foo_default):
            parser.error( "foo before bar!")
        else:
            setattr(namespace,self.dest,values)

parser=argparse.ArgumentParser()
parser.add_argument('--foo',default=foo_default)
parser.add_argument('--bar',action=BarAction,help="Only use this if --foo is set")

#testing.
print parser.parse_args('--foo baz'.split())
print parser.parse_args('--foo baz --bar cat'.split())
print parser.parse_args('--bar dog'.split())

これは、argparse の文書化されていない動作に依存しても問題ない場合は、維持するのが少し簡単な方法で行うこともできます。

import argparse

parser=argparse.ArgumentParser()
first_action=parser.add_argument('--foo',dest='cat',default=None)

class BarAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        didfoo=getattr(namespace,first_action.dest,first_action.default)
        if(didfoo == first_action.default):
            parser.error( "foo before bar!")
        else:
            setattr(namespace,self.dest,values)

parser.add_argument('--bar',action=BarAction,
                    help="Only use this if --foo is set")

#testing.
print parser.parse_args('--foo baz'.split())
print parser.parse_args('--foo baz --bar cat'.split())
print parser.parse_args('--bar dog'.split())

この例では、デフォルトの for を取得しfoo、それはによって返されるアクション オブジェクトから宛先になりますadd_argument(add_argument の戻り値は、私が見つけることができるどこにも文書化されていません)。これはまだ少し壊れやすいです(たとえば、引数にtype=キーワードを指定したい場合)。--foo

sys.argv最後に、解析する前に 確認できます。

import sys
if ("--parameter2" in sys.argv) and ("--parameter1" not in sys.argv):
    parser.error("parameter1 must be given if parameter2 is given")

--parameter1によってもトリガーされる場合、これはもう少しトリッキーになり--p1ますが、アイデアはわかります。次に、使用できます

if (set(sys.argv).intersection(('--p2',...)) and 
    not set(sys.argv).intersection(('--p1',...)))

ここでの利点は、特定の順序を必要としないことです。(コマンドライン--p2でフォローする必要はありません)。--p1そして、前と同様に、option_stringsによって返される属性を介して特定のアクションをトリガーするコマンド文字列のリストを取得できますparser.add_argument(...)。例えば

import argparse
import sys   
parser=argparse.ArgumentParser()
action1=parser.add_argument('--foo')
action2=parser.add_argument('--bar',
                            help="Only use this if --foo is set")

argv=set(sys.argv)
if (( argv & set(action2.option_strings) ) and 
      not ( argv & set(action1.option_strings) )):
                #^ set intersection
     parser.error(' or '.join(action1.option_strings)+
                  ' must be given with '+
                  ' or '.join(action2.option_strings))
于 2012-07-12T15:38:22.593 に答える
4

parse_known_args()を使用して、パーサー--parameter1に追加する前に指定されたかどうかを確認できます。--parameter2

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--parameter1', dest='p1')
args = parser.parse_known_args()[0]
if args.p1:
  parser.add_argument('--parameter2', dest='p2')
args = parser.parse_args()

if args.p1:
  print args.p1
if args.p2:
  print args.p2

結果:

$ python myScript.py --parameter1 a
a
$ python myScript.py --parameter1 a --parameter2 b
a
b
$ python myScript.py --parameter2 b
usage: myScript.py [-h] [--parameter1 P1]
myScript.py: error: unrecognized arguments: --parameter2 b
于 2014-02-25T20:24:02.863 に答える
3

1 つのアイデアは、呼び出しの出力を手動でチェックしparser.parse_args()て例外を発生させるか、使用されていない場合--parameter2は失敗すること--parameter1です。

また、名前空間内に存在するかどうかを確認するカスタム アクションを設定して(少し下にスクロール)試すこともできます。--parameter2--parameter1

最後に、subparsersの使用を試すことができますが、 の値を指定できるかどうかはわかりません--parameter1

于 2012-07-12T15:39:10.377 に答える