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
нет списка.
Как я могу достичь того, чего хочу?
Ответы
Ответ 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
(проверьте документы).
Надеюсь, поможет.