2014-12-08 14 views
0

我已閱讀關於如何定義,解析和運行多個subparsers運行某事像解析多個subparsers,但隨着全球參數

tool.py func_a -a 12 func_b -b 15 input.txt output.txt 
            ^-- main parser args 
        ^--------------- subparser b 
     ^---------------------------- subparser a 

他們通常建議是這樣了不少的問題和答案:

def func_a(args): 
    pass 

def func_b(args): 
    pass 


parser = argparse.ArgumentParser() 
subparsers = parser.add_subparsers() 

# Define subparsers 
subp_a = subparsers.add_parser(func_a.__name__) 
subp_a.set_defaults(func=func_a) 
subp_a.add_argument('-a') 

subp_b = subparsers.add_parser(func_b.__name__) 
subp_b.set_defaults(func=func_b) 
subp_b.add_argument('-b') 

# Define global parameters 
parser.add_argument('input', type=argparse.FileType('r')) 
parser.add_argument('output', type=argparse.FileType('wb', 0)) 

# Parse and run through all arguments 
rest = sys.argv[1:] 
while rest: 
    args, rest = parser.parse_known_args(rest) 
    args.func(args) 

但是,這種實現有一個問題:參數inputoutput是爲主分析器定義的,應該只使用一次。但是,每次調用parser.parse_known_args(rest)都需要設置值,因此將其從rest中刪除。

這意味着第一次調用parse_known_args會檢索值,並且每個後續調用都會由於缺少參數而失敗。

是否有解決方案來克服這個問題,而不需要手動將值複製到rest列表中?

回答

0

是的,第一個parse_known_args消耗文件名以及第一個子分析器級別。

您可以定義2個解析器,一個具有'全局'定位,一個不具有。首先用'with'解析器解析,掛到它的args(用於文件名)。然後使用'without'解析器沿着subparser堆棧前進。

這裏有一個簡單的例子:

parser = argparse.ArgumentParser() 
parser.add_argument('foo') 
subp = parser.add_subparsers(dest='cmd') 
cmd1 = subp.add_parser('cmd1') 
cmd1.add_argument('-a') 
cmd2 = subp.add_parser('cmd2') 
# parser.add_argument('bar') # confusing location 

parser1 = argparse.ArgumentParser() 
subp = parser1.add_subparsers(dest='cmd') 
cmd1 = subp.add_parser('cmd1', parents=[cmd1], add_help=False) 
cmd2 = subp.add_parser('cmd2') 

# Parse and run through all arguments 
args, rest = parser.parse_known_args() 
print args, rest 
while rest: 
    args, rest = parser1.parse_known_args(rest) 
    print args, rest 

我把parserfoosubp之前,因爲它創造有減少混亂。末尾的位置(bar)可能與其中一個子分析器或嵌套子分析器之一的參數混淆 - 特別是在生成錯誤消息時。

要獲得的parse_args將如何參數字符串分配給各個positionals一個想法,嘗試像腳本:

parser = argparse.ArgumentParser() 
parser.add_argument('foo') 
parser.add_argument('cmd', nargs=argparse.PARSER, choices=['cmd1','cmd2']) 
parser.add_argument('bar') 
print parser.parse_args() 

parser,該subparsers說法看起來只是一個喜歡的位置是至少需要一個字符串(有點像'+'),第一個必須匹配choices。它將收到所有剩餘的字符串,符合其他立場的要求。