1 つ以上の入力ファイルを受け取るスクリプトを作成します。スクリプト (A と B) のオプションと、各入力ファイル (C と D) のオプションを個別に指定できるようにしたいと考えています。
使用法は次のようになります。
script.py [-A] [-B] [-C] [-D] file1 [[-C] [-D] file2] ...
どうすればそれを行うことができargparse
ますか?
ありがとうございました!
私はしばらくこれをやりたいと思っていましたが、ユースケースを思いつきませんでした。1 つ見つかりました: ありがとうございます。
これは、2 段階の argparse で行うことができます。-A
最初の段階では、またはオプションのみを探し-B
ます。
第 2 段階では、残りの引数をフラグメントに分割し (この場合はジェネレーター関数を使用) parse_args
、フラグメントを呼び出します。
import argparse
def fileargs(args):
result = []
for arg in args:
result.append(arg)
if not arg.startswith('-'):
yield result
result = []
parser = argparse.ArgumentParser()
parser.add_argument('-A', action = 'store_true')
parser.add_argument('-B', action = 'store_true')
args, unk = parser.parse_known_args()
print(args)
file_parser = argparse.ArgumentParser()
file_parser.add_argument('-C', action = 'store_true')
file_parser.add_argument('-D', action = 'store_true')
file_parser.add_argument('file')
for filearg in fileargs(unk):
fargs = file_parser.parse_args(filearg)
print(fargs)
その後、test.py -A -B -C -D file1 -C file2
利回り
Namespace(A=True, B=True)
Namespace(C=True, D=True, file='file1')
Namespace(C=True, D=False, file='file2')
可能であればdocoptを試してください。はるかに使いやすく、開始するのに十分な例があります。
私の、この答えは複雑です:
import sys
#Unforunately, you can't split up positional arguments in a reasonable way if you
#don't know about all of them... Count positional arguments (files)
def how_many_files(lst):
return sum(1 for x in lst if not x.startswith('-'))
args = sys.argv[1:]
Nfiles = how_many_files(args)
import argparse
#Create our own NameSpace class so that we can have an easy handle on the
#attributes that the namespace actually holds.
class MyNameSpace(argparse.Namespace,dict):
def __init__(self):
argparse.Namespace.__init__(self)
dict.__init__(self)
def __setattr__(self,k,o):
argparse.Namespace.__setattr__(self,k,o)
self[k] = o
class MyParser(argparse.ArgumentParser):
def __init__(self,*args,**kwargs):
self.my_parents = kwargs.get('parents',[])
argparse.ArgumentParser.__init__(self,*args,**kwargs)
class FooAction(argparse.Action):
def __call__(self,parser,namespace,value,option_string=None):
ref = namespace.pop('accumulated',{})
try:
del namespace.accumulated
except AttributeError:
pass
#get a new namespace and populate it with the arguments we've picked up
#along the way
new_namespace = self.__default_namespace(parser)
for k,v in namespace.items():
setattr(new_namespace,k,v)
delattr(namespace,k) #delete things from `namespace.__dict__`
namespace.clear() #also remove things from the dictionary side.
namespace.accumulated = ref
new_namespace.file = value
ref[value] = new_namespace
def __default_namespace(self,parser):
n = argparse.Namespace()
for parent in parser.my_parents:
parent.parse_args([],namespace=n)
return n
parser = argparse.ArgumentParser()
parser.add_argument('-A',action='store_true')
parser.add_argument('-B',action='store_true')
parser.add_argument('-C',action='store_true')
parser.add_argument('-D',action='store_true')
parser2 = MyParser(parents=[parser],conflict_handler='resolve')
for i in range(Nfiles):
parser2.add_argument('files%d'%i,action=FooAction,default=argparse.SUPPRESS)
n = parser2.parse_args(args,namespace = MyNameSpace())
for k,v in n.accumulated.items():
print k,v
これを次のように呼び出します。
~ $ python test.py -A foo bar -A -B -C qux
収量:
qux Namespace(A=True, B=True, C=True, D=False, file='qux')
foo Namespace(A=True, B=False, C=False, D=False, file='foo')
bar Namespace(A=False, B=False, C=False, D=False, file='bar')
いつものように、質問は正確に必要なものではないように見えました..申し訳ありません。これは、引数付きのファイルごとのオプションも許可する私の作業結果です(unutbuの回答に触発されました)。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-A', action = 'store_true')
parser.add_argument('-B', action = 'store_true')
args, unk = parser.parse_known_args()
file_parser = argparse.ArgumentParser()
file_parser.add_argument('-C', action = 'store_true')
file_parser.add_argument('-D', action = 'store_true')
file_parser.add_argument('-V', "--variable-list")
file_parser.add_argument('file')
fargs=[]
n=len(unk)
while True:
i=0
for i in range(n): # finding longest fully parsable tail
Parsed, unkf = file_parser.parse_known_args(unk[i:n])
if not unkf: break
if i==n: # did not found parsable tail
file_parser.parse_args(unk[0:n]) # cause error
else:
fargs.append(Parsed)
n=i
if (n<=0): break
fargs.reverse()
print args
for argl in fargs:
print argl
これを次のように呼び出します。
myscript.py -A -B -C -D file1 -C -V a,b,c file
収量:
Namespace(A=True, B=True)
Namespace(C=True, D=True, file='file1', variable_list=None)
Namespace(C=True, D=False, file='file2', variable_list='a,b,c')
オプションはaction=append
おそらく役立ちます。これにより、オプションを複数回指定でき、特定のオプションを持つすべての引数がそれぞれのリストに保存されます。
...ここに例を示します。それを呼び出しましょうsample.py
:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--cfilein", action="append")
parser.add_argument("-d", "--dfilein", action="append")
args = parser.parse_args()
print args.cfilein
print args.dfilein
Execute: ./sample.py -c f1 -d f2 -c f3 -d f4
Output: ['f1', 'f3']
['f2', 'f4']
チェックアウト: http://docs.python.org/2/library/argparse.html#action ...これが役立つことを願っています...