2015-06-19 24 views
7

Hiçbir değer veya 2 değer alabilen bir komut dosyası için isteğe bağlı argüman yapmaya çalışıyorum, başka bir şey yok. Argparse kullanarak bunu yapabilir misin? Bu birleştirmek yapmak nasılargparse - isteğe bağlı argüman için 2 değeri veya hiçbiri gerekmiyor

parser = argparse.ArgumentParser() 
parser.add_argument("-a", "--action", nargs=2, action="store", help="do some action") 
args = parser.parse_args() 

# output: 
# ./script.py -a --> error 
# ./script.py -a val1 --> error 
# ./script.py -a val1 val2 --> works 


: - Tam olarak kabul 2 değerlerini

parser = argparse.ArgumentParser() 
parser.add_argument("-a", "--action", nargs="?", const=True, action="store", help="do some action") 
args = parser.parse_args() 

# output: 
# ./script.py -a --> works 
# ./script.py -a val1 --> works 
# ./script.py -a val1 val2 --> error 


sürüm 2: -

# desired output: 
# ./script.py -a --> works 
# ./script.py -a val1 --> error 
# ./script.py -a val1 val2 --> works 


sürüm 1 0 veya 1 değerlerini kabul 2 farklı sürümde, betik argüman için 0 veya 2 değerini kabul eder, ancak reddeder Sadece 1 değeri olduğunda?

cevap

6

Burada kontrol etmek kendi hatalarınızı yapmak zorundasınız. 0 veya daha fazla değer kabul edin ve başka bir şey reddetmek 0 veya 2:

hiçbir -a anahtarı kullanıldığında args.action None olarak ayarlanır Not olduğunu
parser = argparse.ArgumentParser() 
parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action") 
args = parser.parse_args() 

if args.action is not None and len(args.action) not in (0, 2): 
    parser.error('Either give no values for action, or two, not {}.'.format(len(args.action))) 

:

>>> import argparse 
>>> parser = argparse.ArgumentParser() 
>>> parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action") 
_StoreAction(option_strings=['-a', '--action'], dest='action', nargs='*', const=None, default=None, type=None, choices=None, help='do some action', metavar=None) 
>>> args = parser.parse_args([]) 
>>> args.action is None 
True 
>>> args = parser.parse_args(['-a']) 
>>> args.action 
[] 
+0

ihtiyacım olan şey: her iki durumda da bir hata istemezsiniz. './script.py -a foo' veya' ./script.py -a foo bar baz' kullandığınızda ve daha uzun bir hata istersiniz. – xgord

+0

@ xgord ile aynı işlevi görürse, bu tam olarak –

+0

@xgord: bu kontrol, '' a' kullanıldığında, ancak hatalı argüman sayısı ile bir hata ortaya çıkarmakla ilgili ''./Script.py' durumunun ele alınmasıyla ilgili değildir. Bunun yerine ne olmasını beklediniz? –

3

Sadece bu durumda kendini kontrol: kullanıcı hatası içine çalıştırmadan önce bu tanıma şansına sahip olacak şekilde

parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action") 
args = parser.parse_args() 

if args.action is not None: 
    if len(args.action) not in (0, 2): 
     parser.error('Specify no or two actions') 

    # action was specified but either there were two actions or no action 
else: 
    # action was not specified 

Tabii ki bu durumda yardım metni güncellemeniz gerekir.

+0

nasıl bu ikisinin arasında pratik bir fark vardır "./script.py -a" – xgord

+0

aynı davranır? – poke

+1

@xgord Aslında aynı davranmıyor. '/ script.py' yaparsanız, args.action'' None' olacaktır; Eğer ./script.py -a 'yaparsanız,' args.action' '[]' olacaktır. – poke

-1

Nasıl Gerekli argüman hakkında: parser.add_argument("-a", "--action", nargs=2, action="store", help="do some action", required=False)

+1

Bu işe yaramaz, '-a' hiçbir değer olmadan bir hata verir çünkü tam olarak 2 eleman değildir. 'required = False' zaten * varsayılan *. –

+1

İsteğe bağlı özellikler ('- like-this -ve-this') argparse ile varsayılan olarak gerekli değildir. – poke

0

Seçeneğiniz, tek, isteğe bağlı virgülle ayrılmış bir dizeyi alsın. Bu dizeyi bir listeye dönüştürmek için özel bir tür kullanırsınız ve tam olarak iki öğenin olduğunu doğrulayın.

def pair(value): 
    rv = value.split(',') 
    if len(rv) != 2: 
     raise argparse.ArgumentParser() 
    return rv 

parser.add_argument("-a", "--action", nargs='?', 
        type=pair, metavar='val1,val2', 
        help="do some action") 
print parser.parse_args() 

Sonra farklı bir ayırıcı kullanmak pair tanımını ayarlayabilir ve (örneğin, bir demet) bir liste dışında bir şey dönmek için

$ ./script.py -a 
Namespace(action=None) 
$ ./script.py -a val1,val2 
Namespace(action=['val1','val2']) 
$ ./script.py -a val1 
usage: tmp.py [-h] [-a [ACTION]] 
script.py: error: argument -a/--action: invalid pair value: 'val1' 
$ ./script.py -a val1,val2,val3 
usage: tmp.py [-h] [-a [ACTION]] 
script.py: error: argument -a/--action: invalid pair value: 'val1,val2,val3' 

gibi kullanmak.

metavar, action argümanının yalnızca bir taneden ziyade bir çift değer olduğunu daha iyi bir şekilde gösterir. Bu çözüm "./script.py" ile

$ ./script.py -h 
usage: script.py [-h] [-a [val1,val2]] 

optional arguments: 
    -h, --help   show this help message and exit 
    -a [val1,val2], --action [val1,val2] 
         do some action 
İlgili konular