2017-01-09 76 views
1

我有一個名爲program.py的程序,我使用argparse來執行參數解析。Python argparse - 不同的選項集

我有兩個模式,我要運行這個二進制搭配: 1)模擬,它不需要參數 2)非模擬,這需要很多爭論

我希望程序要麼接受

python program --simulation 

python program arg1 arg2 arg3 arg4 

如果要求所有的 'ARGS' 的。

我想這樣做的唯一方法是添加'required = False'到所有字段並手動檢查邏輯,但我想知道是否有更優雅的方式。

下面的代碼的削減版本,我有

def get_args(): 
    parser = argparse.ArgumentParser(description = "program") 
    parser.add_argument("arg1", type = bool) 
    parser.add_argument("arg2" ,type = str) 
    parser.add_argument("arg3", type = int) 
    parser.add_argument("arg4", type = str) 
    parser.add_argument("--simulation") 
    args = parser.parse_args() 
    return args 
+0

你使用'type = bool'是有問題的。請參閱我答案中的鏈接。 – hpaulj

回答

1

​​不能是聰明的。然而,在你的簡單的情況下,可以「幫助」它來選擇正確選項解析:

def get_args(args=sys.argv[1:]): 
    parser = argparse.ArgumentParser(description = "program") 
    if args and args[0].startswith("--"): 
     parser.add_argument("--simulation") 
    else: 
     parser.add_argument("arg1", type = bool) 
     parser.add_argument("arg2" ,type = str) 
     parser.add_argument("arg3", type = int) 
     parser.add_argument("arg4", type = str) 
    args = parser.parse_args(args=args) 
    return args 

所以print(get_args("--simulation xx".split()))產量:

Namespace(simulation='xx') 

,因爲第一個參數與--開始。任何其他選項都無法按預期方式執行命令行解析。

print(get_args("True foo 3 bar".split()))收率:

Namespace(arg1=True, arg2='foo', arg3=3, arg4='bar') 

忘記4個位置參數中的一個作爲預期失敗命令行解析。

順便說一句,我已經添加了一個默認參數,如果省略讀取系統參數(就像它在你的代碼中那樣)。否則,您可以從文本文件中讀取並傳遞參數標記。因此,測試更容易,並且可以創建可以使用其他模塊的參數調用的模塊,而無需通過sys.argv進行破解。

+0

工作出色,謝謝!一個簡單的問題是,是否需要向'get_args'提供'參數'?或者,這只是爲了讓它更一般,以防我們想從文本文件中讀取參數? – triplebig

+0

確切地說,看我的編輯。傳遞任何參數都與以前一樣:從命令行解析。 –

1

這顯然是​​的一個尷尬的規範,我懷疑大多數其他POSIX風格的解析器。

掃描sys.argv並調整解析器定義是一種可能的方法。

另一種是用一個2級剖析,以parse_known_args

import argparse 
usage = 'prog [-h] [--simulation] [arg1 arg2 arg3 arg4]' 
parser1 = argparse.ArgumentParser(usage=usage) 
parser1.add_argument('--simulation', action='store_true') 
# or omit the `store_true` if it just takes one argument 
# other possible optionals 

parser2 = argparse.ArgumentParser() 
#parser2.add_argument("arg1", type = bool) # not a valid type parameter 
parser2.add_argument("arg2") 
parser2.add_argument("arg3", type = int) 
parser2.add_argument("arg4") 
# positionals are required, unless nargs=? or * 

args, extras = parser1.parse_known_args() 
if not args.simulation: 
    args = parser2.parse_args(extras, namespace=args) 
elif extras: 
    parser1.error('cannot use --simulation with args') 
print(args) 

可能的運行包括:

1526:~/mypy$ python stack41556997.py -h 
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4] 

optional arguments: 
    -h, --help show this help message and exit 
    --simulation 

1526:~/mypy$ python stack41556997.py --simulation 
Namespace(simulation=True) 

1527:~/mypy$ python stack41556997.py 1 2 3 
Namespace(arg2='1', arg3=2, arg4='3', simulation=False) 

1527:~/mypy$ python stack41556997.py 1 2 3 --sim 
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4] 
stack41556997.py: error: cannot use --simulation with args 

注意,幫助不包括兩套。我在自定義用法中包含了一些信息,但arg#沒有幫助行。生成一個好的help消息將與您的規格尷尬。

我跳過了你的arg1type=bool不是有效的type參數。請參閱我的解釋Parsing boolean values with argparse

我將--simulation更改爲store_true,因爲您說它沒有任何參數。這是接受True/False的正常方式。

Subparsers通常是接受不同模式參數的最佳工具。在這種情況下,你可以有一個叫做'simulate'的subparser不需要任何參數,另一個叫'somethingelse'需要4個參數。

我打算建議一個與--simulation和​​可選項互斥的組。但一個store_true的論點不適用於這樣的組。

=============

子分析器路線:

parser = argparse.ArgumentParser() 
sp = parser.add_subparsers(dest='cmd') 
sp.add_parser('simulate') 
parser2 = sp.add_parser('other') 
parser2.add_argument("arg2") 
parser2.add_argument("arg3", type = int) 
parser2.add_argument("arg4") 
print(parser.parse_args()) 

測試:

1552:~/mypy$ python stack41556997.py -h 
usage: stack41556997.py [-h] {simulate,other} ... 

positional arguments: 
    {simulate,other} 

optional arguments: 
    -h, --help  show this help message and exit 
1557:~/mypy$ python stack41556997.py simulate 
Namespace(cmd='simulate') 
1557:~/mypy$ python stack41556997.py other -h 
usage: stack41556997.py other [-h] arg2 arg3 arg4 

positional arguments: 
    arg2 
    arg3 
    arg4 

optional arguments: 
    -h, --help show this help message and exit 
1557:~/mypy$ python stack41556997.py other 1 2 3 
Namespace(arg2='1', arg3=2, arg4='3', cmd='other') 

注意,arg3type轉換的輸入到一個整數。其他人留作字符串。有了這個設置,args.cmd將成爲子分析器的名稱,與布爾型args.simulation屬性不完全相同。

==================

甲標記默認參數不要求的。位置參數是必需的,除非nargs值爲'?'要麼 '*'。您無法爲位置提供「必需」參數。