2010-11-06 5 views
8

Я пишу сервер запросов инструмент, и у меня есть немного кода для разбора аргументов на самом верху:Python argparse: nargs + или * в зависимости от предыдущего аргумента

# Parse arguments 
p = argparse.ArgumentParser() 
g = p.add_mutually_exclusive_group(required=True) 
g.add_argument('--odam', dest='query_type', action='store_const', 
     const='odam', help="Odamex Master query.") 
g.add_argument('--odas', dest='query_type', action='store_const', 
     const='odas', help="Odamex Server query.") 
p.add_argument('address', nargs='*') 
args = p.parse_args() 

# Default master server arguments. 
if args.query_type == 'odam' and not args.address: 
    args.address = [ 
      'master1.odamex.net:15000', 
      'master2.odamex.net:15000', 
      ] 

# If we don't have any addresses by now, we can't go on. 
if not args.address: 
    print "If you are making a server query, you must pass an address." 
    sys.exit(1) 

Есть ли лучше способ сделать это, желательно все в парсере? Эта последняя ошибка выглядит немного неуместной, и было бы неплохо, если бы я мог сделать nargs для адреса зависеть от того, передается ли -odam или --- odas. Я мог бы создать подпараметр, но это помогло бы выглядеть немного странно, так как он оставил бы часть адресов в команде.

ответ

12

Вы можете сделать это с помощью пользовательских argparse.Action:

import argparse 
import sys 

class AddressAction(argparse.Action): 
    def __call__(self, parser, args, values, option = None): 
     args.address=values 
     if args.query_type=='odam' and not args.address: 
      args.address=[ 
       'master1.odamex.net:15000', 
       'master2.odamex.net:15000', 
       ]   
     if not args.address: 
      parser.error("If you are making a server query, you must pass an address.") 

p = argparse.ArgumentParser() 
g = p.add_mutually_exclusive_group(required=True) 
g.add_argument('--odam', dest='query_type', action='store_const', 
     const='odam', help="Odamex Master query.") 
g.add_argument('--odas', dest='query_type', action='store_const', 
     const='odas', help="Odamex Server query.") 
p.add_argument('address', nargs='*', action=AddressAction) 
args = p.parse_args() 

дает

% test.py --odas 
If you are making a server query, you must pass an address. 
% test.py --odam 
Namespace(address=['master1.odamex.net:15000', 'master2.odamex.net:15000'], query_type='odam') 
% test.py --odam 1 2 3 
Namespace(address=['1', '2', '3'], query_type='odam') 
+0

Именно то, что я искал! – AlexMax

+0

Возможно, имеет смысл использовать ошибку [parser error] (http://docs.python.org/library/argparse.html#argparse.ArgumentParser.error) вместо 'sys.exit()' – Christoph

+0

@Christoph: True; благодаря! – unutbu