2012-02-29 3 views
21

Я хотел бы иметь программу, которая принимает --action= флаг, где действительные выборы dump и upload, с upload быть по умолчанию. Если (и только если) выбрано dump, я бы хотел, чтобы там был также номер --dump-format=. Есть ли способ выразить это с помощью argparse, или мне нужно просто принять все аргументы и самостоятельно выполнить логику.Условные аргументы командной строки в Python с использованием argparse

+0

ли жизнеспособный вариант (эстетическая точка зрения), чтобы сделать что-то вроде '--action = свалки -csv' или '--action = dump-some-other-format'? Это позволило бы устранить проблему «требуемых вариантов». – dcrosta

+0

@ dcrosta это, очевидно, сработает, но я предпочитаю не идти таким образом, я нахожу это громоздким. –

+0

Справедливо, просто хотел убедиться, что вы накрыли очевидные базы. – dcrosta

ответ

16

Вы можете использовать parser.error:

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument('--action', choices=['upload', 'dump'], default='dump') 
parser.add_argument('--dump-format') 
args = parser.parse_args() 
if args.action != 'dump' and args.dump_format: 
    parser.error('--dump-format can only be set when --action=dump.') 
+4

Это только описание «аргументированного способа» сообщения об ошибке. Логика реализована вручную. Не является «аргументным» способом условно требующих аргументов. –

+0

Если вместо «дампа» и «форматирования» есть еще 5 вариантов, у каждого из которых есть свой набор необходимых или необязательных аргументов, этот способ проверки необходимости может быстро стать неясным. –

+0

Кроме того, такие вещи, как argparse.FileType, получат проблемы. Для некоторых выбранных действий, когда аргумент FileType не нужен, несуществование файла вызывает ложную ошибку. – Syncopated

34

Другим способом подойти к решению проблемы заключается в использовании subcommands (a'la мерзавца) с "действиями" в качестве первого аргумента:

script dump --dump-format="foo" 
script upload 
+0

Спасибо, мне очень помогли! –

+1

Это должен быть принятый ответ. – itsafire

27

argparse модуль предлагает способ сделать это, не выполняя собственные проверки безопасности . В приведенном ниже примере используются «подпарамеры» или «подкоманды». Я реализовал подпараметр для «дампа» и один для «формата».

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('file', help='The file you want to act on.') 
subparsers = parser.add_subparsers(dest='subcommand') 

# subparser for dump 
parser_dump = subparsers.add_parser('dump') 
# add a required argument 
parser_dump.add_argument(
    'format', 
    choices=['csv', 'json'], 
    help='Dump the file in this format.') 

# subparser for upload 
parser_upload = subparsers.add_parser('upload') 
# add a required argument 
parser_upload.add_argument(
    'server', 
    choices=['amazon', 'imgur'], 
    help='Upload the file to this service.') 

args = parser.parse_args() 
print args 
if args.subcommand == 'dump': 
    print 'I will now dump "%s" in the %s format' % (args.file, args.format) 
if args.subcommand == 'upload': 
    print 'I will now upload "%s" to %s' % (args.file, args.server) 

Это выглядит следующим образом в командной строке:

$ python ap.py 
usage: ap.py [-h] file {upload,dump} ... 
ap.py: error: too few arguments 
$ python ap.py tmp.txt 
usage: ap.py [-h] file {upload,dump} ... 
ap.py: error: too few arguments 
$ python ap.py tmp.txt upload 
usage: ap.py file upload [-h] {amazon,imgur} 
ap.py file upload: error: too few arguments 
$ python ap.py tmp.txt upload amazo 
usage: ap.py file upload [-h] {amazon,imgur} 
ap.py file upload: error: argument server: invalid choice: 'amazo' (choose from 'amazon', 'imgur') 
$ python ap.py tmp.txt upload amazon 
Namespace(file='tmp.txt', server='amazon', subcommand='upload') 
I will now upload "tmp.txt" to amazon 
$ python ap.py tmp.txt upload imgur 
Namespace(file='tmp.txt', server='imgur', subcommand='upload') 
I will now upload "tmp.txt" to imgur 
$ python ap.py tmp.txt dump 
usage: ap.py file dump [-h] {csv,json} 
ap.py file dump: error: too few arguments 
$ python ap.py tmp.txt dump csv 
Namespace(file='tmp.txt', format='csv', subcommand='dump') 
I will now dump "tmp.txt" in the csv format 
$ python ap.py tmp.txt dump json 
Namespace(file='tmp.txt', format='json', subcommand='dump') 
I will now dump "tmp.txt" in the json format 

Подробнее: http://docs.python.org/dev/library/argparse.html#argparse.ArgumentParser.add_subparsers

+0

Это должен быть принятый ответ. – mbrandalero

Смежные вопросы