2011-03-10 19 views
9

Programım için, bazı isteğe bağlı parametrelerle birlikte gerekli bazı parametrelere sahip bir argümana sahip olmak isterim. Böyle bir şey:Python argparse isteğe bağlı alt argümanlar

[--print text [color [size]] 

böylece bunlardan herhangi bunu geçebileceği: tek add_argument olmak zorunda böylece

mycommand --print hello 
mycommand --print hello blue 
mycommand --print hello red 12 

Bunlardan birden de olabilir. Örneğin:

>>> parser = argparse.ArgumentParser() 
>>> act = parser.add_argument('--foo', nargs=3, metavar=('x','y','z')) 
>>> act = parser.add_argument('--bar', nargs='?') 
>>> act = parser.add_argument('--baz', nargs='*') 
>>> parser.print_help() 
usage: [-h] [--foo x y z] [--bar [BAR]] [--baz [BAZ [BAZ ...]]] 

optional arguments: 
    -h, --help   show this help message and exit 
    --foo x y z 
    --bar [BAR] 
    --baz [BAZ [BAZ ...]] 

ama tamamen değil:

[--print text [color]] [--output filename [overwrite]] 

Ne istediğimi yakın argümanları elde edebilirsiniz. Bunu argparse ile yapmanın bir yolu var mı? Bunların hepsini nargs="*" yapabildiğimi biliyorum ama sonra --help isteğe bağlı argümanların isimlerini listelemezdi. nargs="*" ve metavar için bir tuple iletirseniz, argparse bir istisna atar.

cevap

5

source code'u (take_action’dan başlayarak) okumak istediğinizi imkansız kılacağınıza inanıyorum. Tüm argüman ayrıştırma ve eylemlere geçen nargs dayalı yapılır ve nargs ya bir numara, OPTIONAL ("?"), ZERO_OR_MORE ("*"), ONE_OR_MORE ("+"), PARSER veya REMAINDER olduğunu. Bu, Action nesnesinin (girişi ele alan), ne aldığını bile görmeden önce belirlenmelidir, bu nedenle nargs'u dinamik olarak çözemez.

Bence bir geçici çözümle yaşamalısın. Belki de --foo-x x, --foo-y y ve --foo-z z ve belki de --foo x y z.

+1

Teşekkürler. Bu çok kötü. – jterrace

7

Sonra böyle bir şey olsun

def printText(args): 
    print args 

parser = argparse.ArgumentParser() 
subparser = parser.add_subparsers() 
printer = subparser.add_parser('print') 
printer.add_argument('text') 
printer.add_argument('color', nargs='?') 
printer.add_argument('size', type=int, nargs='?') 
printer.set_defaults(func=printText) 

cmd = parser.parse_args() 
cmd.func(cmd) 

nereden: Tek arg için çalışacak

$ ./test.py -h 
usage: test.py [-h] {print} ... 

positional arguments: 
    {print} 

$ ./test.py print -h 
usage: test.py print [-h] text [color] [size] 

positional arguments: 
    text 
    color 
    size 

$ ./test.py print text 
Namespace(color=None, func=<function printText at 0x2a96150b90>, size=None, text='text') 

$ ./test.py print text red 
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=None, text='text') 

$ ./test.py print text red 12 
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=12, text='text') 
+0

Ancak, bir kerede yalnızca bir alt değerlendiriciyi belirtebilirsiniz, bu çoklu olarak çalışmayacaktır. – jterrace

+0

Birden çok örnek verebilir misiniz? Benim örneğim isteğe bağlı konumsal argümanlara gelir, her ikisi de narkoz = '?', Ne yapmanız gerektiğine bağlı olarak, subparser olmadan başarılabilir. ya da çoklu altparçalar .. :) – CNeo

+0

OP'mde bir örnek var: mycommand - print merhaba kırmızı 12 - çıkış dosya adı üzerine yaz – jterrace

0

: Devin jeanpierre cevabı göre

parser.add_argument('--write_google', nargs='?', const='Yes', 
        choices=['force', 'Yes'], 
        help="write local changes to google") 
1

, öyle görünüyor '+' yerine '+' (bir veya daha fazla) kullanmak, elde etmeye çalıştığınız şeyi yapar. (PS: Eğer yeterli puanlarım varsa onun cevabını yorumlayabilirdim)

+0

Unutma-- o da üçten fazla argüman istemiyor.Eğer bunu gönderinin içine sokarsan, o zaman bağımsız bir cevap gönderebilirsin (eğer tabii ki, Jean Pierre fikrinden dolayı kredi alırsan). – Alex

İlgili konular