2011-10-23 81 views
47

Python2.7 argparse只接受可選參數(前綴)在相互排斥的組:如何使python argparse不帶前綴的互斥組參數?

parser = argparse.ArgumentParser(prog='mydaemon') 
action = parser.add_mutually_exclusive_group(required=True) 
action.add_argument('--start', action='store_true', help='Starts %(prog)s daemon') 
action.add_argument('--stop', action='store_true', help='Stops %(prog)s daemon') 
action.add_argument('--restart', action='store_true', help='Restarts %(prog)s daemon') 

$ mydaemon -h

usage: mydaemon [-h] (--start | --stop | --restart) 

optional arguments: 
    -h, --help show this help message and exit 
    --start  Starts mydaemon daemon 
    --stop  Stops mydaemon daemon 
    --restart Restarts mydaemon daemon 

有沒有一種方法,使argparse參數的行爲類似於傳統的UNIX守護程序控制:

(start | stop | restart) and not (--start | --stop | --restart) ? 

回答

52

對於所有我不認爲你永遠得到一個「罐頭」的使用字符串的能力和在​​選項長相就像你想要的一樣。

這就是說,自從你原來的文章以來,你有沒有看過子解析器?

這裏是一個準系統實現:

import argparse 

parser = argparse.ArgumentParser(prog='mydaemon') 
sp = parser.add_subparsers() 
sp_start = sp.add_parser('start', help='Starts %(prog)s daemon') 
sp_stop = sp.add_parser('stop', help='Stops %(prog)s daemon') 
sp_restart = sp.add_parser('restart', help='Restarts %(prog)s daemon') 

parser.parse_args() 

-h選項產量運行此:

usage: mydaemon [-h] {start,stop,restart} ... 

positional arguments: 
    {start,stop,restart} 
    start    Starts mydaemon daemon 
    stop    Stops mydaemon daemon 
    restart    Restarts mydaemon daemon 

一個這種方法的好處是能夠使用set_defaults每個子解析器直接將函數掛接到參數。我還添加了stoprestart 「優雅」 選項:

import argparse 

def my_stop(args): 
    if args.gracefully: 
     print "Let's try to stop..." 
    else: 
     print 'Stop, now!' 

parser = argparse.ArgumentParser(prog='mydaemon') 

graceful = argparse.ArgumentParser(add_help=False) 
graceful.add_argument('-g', '--gracefully', action='store_true', help='tries to terminate the process gracefully') 
sp = parser.add_subparsers() 
sp_start = sp.add_parser('start', help='Starts %(prog)s daemon') 
sp_stop = sp.add_parser('stop', parents=[graceful], 
        description='Stops the daemon if it is currently running.', 
        help='Stops %(prog)s daemon') 
sp_restart = sp.add_parser('restart', parents=[graceful], help='Restarts %(prog)s daemon') 

sp_stop.set_defaults(func=my_stop) 

args = parser.parse_args() 
args.func(args) 

顯示的 「幫助」 消息stop

$ python mydaemon.py stop -h 
usage: mydaemon stop [-h] [-g] 

Stops the daemon if it is currently running. 

optional arguments: 
    -h, --help  show this help message and exit 
    -g, --gracefully tries to terminate the process gracefully 

停止 「正常」:

$ python mydaemon.py stop -g 
Let's try to stop... 
+0

但是,您並未顯示如何確定選擇了哪個啓動停止或重新啓動選項。當我嘗試查看參數的repr時,沒有顯示任何子分析器參數。 –

33

這聽起來像你想要一個位置參數,而不是互斥選項。您可以使用'選項'來限制可能的可接受選項。

parser = ArgumentParser() 
parser.add_argument('action', choices=('start', 'stop', 'restart')) 

這將產生一個使用習慣,看起來像這樣:

usage: foo.py [-h] {start,stop,restart} 
+0

是的,我看到了,但選擇限制了使用的表達性。我只是尋找一些方法來擺脫前綴。 –

+0

你是什麼意思「限制使用的表達」?用戶可以運行腳本而不提供其中之一嗎? –

+0

當用戶發出「mydaemon -h」時,幫助(用法)不像使用每個參數的幫助字符串那麼清楚。 –

11

建立在亞當的答案上......如果你想指定一個默認值,你總是可以做下面的事情,這樣他們可以有效地將它留空。

import argparse 

ActionHelp = """ 
    Start = Starts the daemon (default) 
    Stop = Stops the daemon 
    Restart = Restarts the daemon 
    """ 
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) 

parser.add_argument('action', nargs = '?', choices=('start', 'stop', 'restart'), 
    default = 'start', help = ActionHelp) 

print parser.parse_args(''.split()) 
print 
print parser.parse_args('-h'.split()) 

它將打印:

Namespace(action='start') 

usage: program.py [-h] [{start,stop,restart}] 

postional arguments: 
    {start,stop,restart} 
         Start = Starts the daemon (default) 
         Stop = Stops the daemon 
         Restart = Restarts the daemon 

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

pymotw

import argparse 

parser = argparse.ArgumentParser() 

group = parser.add_mutually_exclusive_group() 
group.add_argument('-a', action='store_true') 
group.add_argument('-b', action='store_true') 

print parser.parse_args() 

輸出:

$ python argparse_mutually_exclusive.py -h 
usage: argparse_mutually_exclusive.py [-h] [-a | -b] 

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

$ python argparse_mutually_exclusive.py -a 
Namespace(a=True, b=False) 

$ python argparse_mutually_exclusive.py -b 
Namespace(a=False, b=True) 

$ python argparse_mutually_exclusive.py -a -b 
usage: argparse_mutually_exclusive.py [-h] [-a | -b] 
argparse_mutually_exclusive.py: error: argument -b: not allowed with argument -a 

version2

import argparse 

parser = argparse.ArgumentParser() 

subparsers = parser.add_subparsers(help='commands') 

# A list command 
list_parser = subparsers.add_parser('list', help='List contents') 
list_parser.add_argument('dirname', action='store', help='Directory to list') 

# A create command 
create_parser = subparsers.add_parser('create', help='Create a directory') 
create_parser.add_argument('dirname', action='store', help='New directory to create') 
create_parser.add_argument('--read-only', default=False, action='store_true', 
         help='Set permissions to prevent writing to the directory', 
         ) 

# A delete command 
delete_parser = subparsers.add_parser('delete', help='Remove a directory') 
delete_parser.add_argument('dirname', action='store', help='The directory to remove') 
delete_parser.add_argument('--recursive', '-r', default=False, action='store_true', 
         help='Remove the contents of the directory, too', 
         ) 

print parser.parse_args(['list', 'a s d', ]) 
>>> Namespace(dirname='a s d') 
print parser.parse_args(['list', 'a s d', 'create' ]) 
>>> error: unrecognized arguments: create 
相關問題