Подтвердить что ты не робот

Argparse: проверьте, не были ли приняты какие-либо аргументы

My script должен запустить демонстрационный режим, когда не заданы никакие параметры. Я пробовал это:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

Что дает *** TypeError: object of type 'Namespace' has no len() как args нет списка.

Как я могу достичь того, чего хочу?

4b9b3361

Ответ 1

Если ваша цель состоит в том, чтобы определить, когда команда не имеет аргумента, тогда выполнение этого с помощью argparse является неправильным подходом (как хорошо заметил Бен).

Подумайте просто!:-) Я считаю, что argparse не опустошает sys.argv. Итак, if not len(sys.argv) > 1, то пользователь не предоставил никаких аргументов.

Ответ 2

argparse позволяет вам установить (внутри объекта пространства имен) все переменные, упомянутые в аргументах, добавленных в парсер, на основе вашей спецификации и анализируемой командной строки. Если вы установите значение по умолчанию, то эти переменные будут иметь это значение по умолчанию, если они не были видны в командной строке, они не будут отсутствовать в объекте пространства имен. И если вы не укажете значение по умолчанию, то существует неявное значение по умолчанию None. Таким образом, проверка длины объекта пространства имен, однако вам удается это сделать, не имеет смысла как способ проверить, были ли проанализированы любые аргументы; он должен всегда иметь одинаковую длину.

Вместо этого, если вы знаете, что у вас есть куча аргументов без настроек по умолчанию, и вы хотите проверить, было ли какое-либо из них настроено на любое значение не None... сделайте это. Вы можете использовать понимание списка и функцию vars, чтобы перебрать их, не дублируя список имен из вызовов add_argument, как показано в ответе Martijn.

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

Ответ 3

Если действительно нужен номер аргумента (по какой-либо причине). Я нашел этот код очень полезным (но не знаю, насколько он оптимизирован, и я был бы признателен за любые комментарии к нему).

args = parser.parse_args()
print( len( vars(args) ) )

В этой версии учитываются только параметры -xx, а не какое-либо дополнительное значение.

Если вы хотите все (также переданные значения), просто используйте len(sys.argv), как упоминалось ранее.

Ответ 4

Не используйте argparse. Вместо этого просто используйте sys.argv. argparse создает пространство имен, поэтому оно всегда будет давать вам "dict" со своими значениями, в зависимости от того, какие аргументы вы использовали, когда вызывали скрипт.

Вот что я сделал в прошлом:

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args

Ответ 5

Предположим, что следующий пример расширяет ваши возможности для полноты:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __name__ == '__main__':
    main()

Ваш объект пространства имен, упомянутый @Ben, в этом примере args. Из строк в parser.add_argument создается переменная. Вы можете получить доступ к нему через args.input или args.length или args.verbose. Вы можете проверить это, выполнив print(args), который на самом деле будет показывать что-то вроде этого:

Namespace(input=None, length=None, verbose=False)

поскольку verbose имеет значение True, если присутствует, а вход и длина - просто переменные, которые не обязательно должны быть созданы (без аргументов).

Также полезно group = parser.add_mutually_exclusive_group(), если вы хотите обеспечить, два атрибута не могут быть предоставлены одновременно.

Для получения дополнительной информации обратитесь к:

Ответ 6

Я расширил концепцию 2dvisio, чтобы считать ненулевые или None аргументы:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])

Ответ 7

Я знаю, что это старая ветка, но я нашел более прямое решение, которое может быть полезным и для других:

Вы можете проверить, были ли переданы какие-либо аргументы:

if any(vars(args).values()):
    # evaluate args

Или, если аргументы не переданы (обратите внимание на оператор not):

if not any(vars(args).values()):
    run_demo()

Объяснение:

  • parse_args() возвращает объект "Пространство имен", содержащий каждое имя аргумента и связанное с ним значение. Пример: Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • Если аргументы не переданы, parse_args() вернет тот же объект, но со всеми значениями, как None. Пример: Namespace(arg1=None, arg2=None)

Этот объект не является итеративным, поэтому вы должны использовать vars() чтобы превратить его в dict чтобы мы могли получить доступ к значениям.

Наконец, так как у нас теперь есть dict, мы можем получить все значения (в list) с помощью .values() и использовать встроенную функцию any() чтобы проверить, не является ли какое-либо из значений None. Чтобы было понятнее: any() возвращает False если в списке, который вы ему направили, нет ни одного значения, None, False или 0 (проверьте документы).

Надеюсь, поможет.