Требуется простой пример argparse: 1 аргумент, 3 результата - PullRequest
491 голосов
/ 15 сентября 2011

Документация для модуля Python Argparse , хотя я уверен, что это превосходно, слишком много, чтобы мой крошечный мозг новичка мог понять прямо сейчас.Мне не нужно делать математику в командной строке или вмешиваться в форматирование строк на экране или изменять параметры символов.Все, что я хочу сделать, это "Если arg равен A, сделайте это, если B сделает это, если ничего из вышеперечисленного не показывает справку и выйдите" .

Ответы [ 9 ]

338 голосов
/ 15 сентября 2011

Вот как я делаю это с argparse (с несколькими аргументами):

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())

args будет словарём, содержащим аргументы:

if args['foo'] == 'Hello':
    # code here

if args['bar'] == 'World':
    # code here

В вашем случае просто добавьте только один аргумент.

229 голосов
/ 26 февраля 2014

Мое понимание первоначального вопроса двоякое.Во-первых, с точки зрения простейшего возможного примера argparse, я удивлен, что не видел его здесь.Конечно, чтобы быть простым, это также накладные расходы с небольшой мощностью, но это может помочь вам начать.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()

if args.a == 'magic.name':
    print 'You nailed it!'

Но этот позиционный аргумент теперь необходим.Если вы пропустите это при вызове этой программы, вы получите ошибку об отсутствующих аргументах.Это приводит меня ко второй части исходного вопроса.Мэтт Уилки, кажется, хочет один необязательный аргумент без именованной метки (метки --option).Я бы предложил изменить приведенный выше код следующим образом:

...
parser.add_argument("a", nargs='?', default="check_string_for_empty")
...
if args.a == 'check_string_for_empty':
    print 'I can tell that no argument was given and I can deal with that here.'
elif args.a == 'magic.name':
    print 'You nailed it!'
else:
    print args.a

Возможно, есть более элегантное решение, но оно работает и является минималистским.

197 голосов
/ 13 декабря 2011

Документация argparse достаточно хороша, но пропускает несколько полезных деталей, которые могут быть неочевидны.(@Diego Navarro уже упоминал кое-что из этого, но я попытаюсь немного расширить его ответ.) Основное использование выглядит следующим образом:

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--my-foo', default='foobar')
parser.add_argument('-b', '--bar-value', default=3.14)
args = parser.parse_args()

Объект, который вы получаете от parse_args(), является пространством имен'объект: объект, чьи переменные-члены названы после ваших аргументов командной строки.Объект Namespace - это способ доступа к аргументам и связанным с ними значениям:

args = parser.parse_args()
print args.my_foo
print args.bar_value

(обратите внимание, что argparse заменяет '-' в именах аргументов подчеркиванием при именовании переменных.)

Во многих ситуациях вы можете использовать аргументы просто как флаги, которые не имеют значения.Вы можете добавить их в argparse следующим образом:

parser.add_argument('--foo', action='store_true')
parser.add_argument('--no-foo', action='store_false')

Выше будут созданы переменные с именами 'foo' со значением True и 'no_foo' со значением False соответственно:

if (args.foo):
    print "foo is true"

if (args.no_foo is False):
    print "nofoo is false"

Также обратите внимание, что вы можете использовать опцию «required» при добавлении аргумента:

parser.add_argument('-o', '--output', required=True)

Таким образом, если вы пропустите этот аргумент в командной строке, argparse сообщит вам, что он отсутствует, и прекратит выполнение вашего скрипта.

Наконец, обратите внимание, что можно создать сложную структуру ваших аргументов с помощью функции vars, если это облегчит вам жизнь.

args = parser.parse_args()
argsdict = vars(args)
print argsdict['my_foo']
print argsdict['bar_value']

Как видите,vars возвращает dict с именами аргументов в качестве ключей, а их значения в качестве значений.

Существует множество других опций и вещей, которые вы можете сделать, но это должно охватывать наиболее важные, распространенные сценарии использования..

56 голосов
/ 29 апреля 2012

Мэтт спрашивает о позиционных параметрах в argparse, и я согласен, что в документации по Python по этому аспекту отсутствует.На ~ 20 нечетных страницах нет ни одного полного примера, показывающего как разбор, так и использование позиционных параметров .

Ни один из других ответов здесь не показывает полный пример позиционных параметров, так что вот полный пример:

# tested with python 2.7.1
import argparse

parser = argparse.ArgumentParser(description="An argparse example")

parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)')
parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments')

args = parser.parse_args()

if args.action == "install":
    print("You asked for installation")
else:
    print("You asked for something other than installation")

# The following do not work:
# print(args.foo-bar)
# print(args.foo_bar)

# But this works:
print(getattr(args, 'foo-bar'))

Меня поразило то, что argparse преобразует именованныеаргумент "--foo-bar" в "foo_bar", но позиционный параметр с именем "foo-bar" остается как "foo-bar", делая менее очевидным, как использовать его в вашей программе.

Обратите внимание на две строки в конце моего примера - ни одна из них не сработает, чтобы получить значение позиционного параметра foo-bar.Первое, очевидно, неверное (это арифметическое выражение args.foo минус бар), но второе тоже не работает:

AttributeError: 'Namespace' object has no attribute 'foo_bar'

Если вы хотите использовать атрибут foo-bar, вы должныиспользуйте getattr, как показано в последней строке моего примера.Сумасшествие заключается в том, что если вы попытаетесь использовать dest=foo_bar для изменения имени свойства на что-то более простое, вы получите действительно странное сообщение об ошибке:

ValueError: dest supplied twice for positional argument

Вот как работает приведенный выше пример:

$ python test.py
usage: test.py [-h] action foo-bar
test.py: error: too few arguments

$ python test.py -h
usage: test.py [-h] action foo-bar

An argparse example

positional arguments:
  action      The action to take (e.g. install, remove, etc.)
  foo-bar     Hyphens are cumbersome in positional arguments

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

$ python test.py install foo
You asked for installation
foo
15 голосов
/ 12 марта 2018

Еще одно краткое введение, вдохновленное этой публикацией .

import argparse

# define functions, classes, etc.

# executes when your script is called from the command-line
if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    #
    # define each option with: parser.add_argument
    #
    args = parser.parse_args() # automatically looks at sys.argv
    #
    # access results with: args.argumentName
    #

Аргументы определяются с помощью следующих комбинаций:

parser.add_argument( 'name', options... )              # positional argument
parser.add_argument( '-x', options... )                # single-char flag
parser.add_argument( '-x', '--long-name', options... ) # flag with long name

Общееварианты:

  • help : описание этого аргумента при использовании --help.
  • default : значение по умолчанию, если argопущен
  • введите : если вы ожидаете float или int (в противном случае str).
  • dest : укажите другоеимя для флага (например, '-x', '--long-name', dest='longName').
    Примечание: по умолчанию к --long-name обращаются с помощью args.long_name
  • действие : для специальной обработкинекоторых аргументов
    • store_true, store_false: для логических аргументов
      '--foo', action='store_true' => args.foo == True
    • store_const: для использования с параметром const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count: для повторяющихся опций, как в ./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append: для повторяющихся опций, как в ./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • обязательный : если требуется флаг или позиционный аргументis not.
  • nargs : для флага для захвата N args
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • выборов : для ограничения возможных вводов (укажитев виде списка строк или целых, если type=int).
11 голосов
/ 13 марта 2016

Обратите внимание на Argparse Tutorial в Python HOWTO .Он начинается с большинства базовых примеров, таких как этот:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

и переходит к менее базовым.

Существует пример с предопределенным выбором для опции, например, что спрашивается:1010 *

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)
10 голосов
/ 18 июня 2016

Вот что я придумал в своем учебном проекте, в основном благодаря @DMH ...

Демо-код:

import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--flag', action='store_true', default=False)  # can 'store_false' for no-xxx flags
    parser.add_argument('-r', '--reqd', required=True)
    parser.add_argument('-o', '--opt', default='fallback')
    parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more)
    parsed = parser.parse_args()
    # NOTE: args with '-' have it replaced with '_'
    print('Result:',  vars(parsed))
    print('parsed.reqd:', parsed.reqd)

if __name__ == "__main__":
    main()

Возможно, это произошло и доступно онлайн: command-line.py

Скрипт для тренировки этого кода: command-line-demo.sh

4 голосов
/ 08 октября 2016

Вы также можете использовать plac (обертка вокруг argparse).

В качестве бонуса он генерирует аккуратные инструкции помощи - см. Ниже.

Пример сценария:

#!/usr/bin/env python3
def main(
    arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B'])
):
    """General help for application"""
    if arg == 'A':
        print("Argument has value A")
    elif arg == 'B':
        print("Argument has value B")

if __name__ == '__main__':
    import plac
    plac.call(main)

Пример вывода:

Не указаны аргументы - example.py:

usage: example.py [-h] {A,B}
example.py: error: the following arguments are required: arg

Неожиданный аргумент предоставлен - example.py C:

usage: example.py [-h] {A,B}
example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B')

Указан правильный аргумент - example.py A:

Argument has value A

Меню полной справки (генерируется автоматически) - example.py -h:

usage: example.py [-h] {A,B}

General help for application

positional arguments:
  {A,B}       Argument with two possible values

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

Краткое объяснение:

Имя аргумента обычно равно имени параметра (arg).

Аннотация кортежа после *Параметр 1042 * имеет следующее значение:

  • Описание (Argument with two possible values)
  • Тип аргумента - один из 'flag', 'option' или 'positional' (positional)
  • Сокращение (None)
  • Тип значения аргумента - например.float, string (None)
  • Ограниченный набор вариантов (['A', 'B'])

Документация:

Чтобы узнать больше об использовании plac посмотрите большую документацию:

Plac: легкий анализ командной строки

4 голосов
/ 12 декабря 2013

Чтобы добавить к тому, что заявили другие:

Я обычно хотел бы использовать параметр 'dest', чтобы указать имя переменной, а затем использовать 'globals (). Update ()', чтобы поместить эти переменные вглобальное пространство имен.

Использование:

$ python script.py -i "Hello, World!"

Код:

...
parser.add_argument('-i', '--input', ..., dest='inputted_variable',...)
globals().update(vars(parser.parse_args()))
...
print(inputted_variable) # Prints "Hello, World!"
...