Перевірте, встановлений чи ні аргументальний параметр argparse


112

Я хотів би перевірити, встановлений необов'язковий аргумент argparse користувачем чи ні.

Чи можу я безпечно перевірити використання isset?

Щось на зразок цього:

if(isset(args.myArg)):
    #do something
else:
    #do something else

Чи працює це так само для аргументів типу float / int / string?

Я міг би встановити параметр за замовчуванням і перевірити його (наприклад, встановити myArg = -1, або "" для рядка або "NOT_SET"). Однак значення, яке я в кінцевому підсумку хочу використовувати, обчислюється лише пізніше в сценарії. Тож я встановив би його як -1 за замовчуванням, а потім оновив його до чогось іншого пізніше. Це здається трохи незграбним у порівнянні з простою перевіркою, чи встановлено значення користувачем.


1
Що було isset()б (натяк: Python не PHP)? Ти мав на увазі, hasattr()натомість? Чому б не налаштувати argparse для встановлення за замовчуванням для параметра?
Martijn Pieters

@MartijnPieters - так, правда. Тож я можу просто перевірити, чи (args.myArg): ...
Мадлен П. Вінсент

Відповіді:


146

Я думаю, що необов'язкові аргументи (вказані з --) ініціалізуються, Noneякщо вони не надаються. Тож можна спробувати is not None. Спробуйте наведений нижче приклад:

import argparse as ap

def main():
    parser = ap.ArgumentParser(description="My Script")
    parser.add_argument("--myArg")
    args, leftovers = parser.parse_known_args()

    if args.myArg is not None:
        print "myArg has been set (value is %s)" % args.myArg

Тести "немає" і "немає" працюють точно так, як я хотів би і очікував. Дякую.
Мадлен П. Вінсент

39
На жаль, він не працює, тоді аргумент defaultвизначив його значення.
kcpr

6
Якщо ви хочете встановити a default, ви все одно можете встановити nargs='?'та надати constзначення, як описано в документах . Коли аргумент відсутній, defaultвикористовується, коли аргументується значення w / o, то constвикористовується, інакше використовується задане значення. З тільки defaultі nargs='?', defaultвикористовується, якщо не задано, Noneякщо задано значення без огляду, інакше задане значення.
Іоанніс Філіппідіс

@IoannisFilippidis, якщо ви використовуєте action= "store_true"або action="store_const", const="yourconst"не можете використовувати цей аргумент для зберігання іншого значення. Це не буде працювати при використанні значень за замовчуванням. По-моєму я видалив усі параметри за замовчуванням з argparser і обробив все всередині іншої функції, def defaults():де я змішую ConfigParser, ArgumentParser і значення за замовчуванням у тому порядку, який я хочу
m3nda

@ erm3nda Я не згадав про встановлення action. У відповіді не використовується ан action. Дії, про які ви згадуєте, задокументовано, щоб вони поводилися певним чином (як ви зауважили). Однак не потрібно визначати дію.
Іоанніс Філіппідіс

37

Як зазначає @Honza is None, це хороший тест. Це за замовчуванням default, і користувач не може дати вам рядок, який дублює його.

Ви можете вказати інше default='mydefaultvalueі протестувати це. Але що робити, якщо користувач вказав цей рядок? Чи вважається це налаштуванням чи ні?

Ви також можете вказати default=argparse.SUPPRESS. Тоді якщо користувач не використовує аргумент, він не з’явиться в argsпросторі імен. Але тестування, яке може бути складніше:

args.foo # raises an AttributeError
hasattr(args, 'foo')  # returns False
getattr(args, 'foo', 'other') # returns 'other'

Внутрішньо parserзберігає список seen_actionsта використовує його для тестування "вимагається" та "взаємно-ексклюзивно". Але це недоступно для вас поза стороною parse_args.


22

Я думаю, використовуючи варіант default=argparse.SUPPRESS має найбільше сенс. Потім, замість того, щоб перевіряти, чи є аргумент not None, перевіряється, чи є аргумент inвнаслідок цього простором імен.

Приклад:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--foo", default=argparse.SUPPRESS)
ns = parser.parse_args()

print("Parsed arguments: {}".format(ns))
print("foo in namespace?: {}".format("foo" in ns))

Використання:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
Аргумент не надається:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

Це не працює для мене в Python 3.7.5 (Anaconda). Я отримую результатtestfoo.py: error: argument --foo: expected one argument
Майк Мудрий

@MikeWise Якщо ви хочете використовувати --fooбез значення (тобто 1в моєму прикладі), ви повинні вказати nargs=0у add_argumentфункції.
Еразм Седерней

Я просто копіюю і вставляю ваш код, як зазначено у відповіді. Можливо, вам слід це відредагувати? Я в кінцевому підсумку використав action='store_true'відповідь нижче, ніж у своєму фактичному коді.
Майк Мудрий

@MikeWise ти запустив сценарій як python argparse_test.py --foo 1?
Еразм Седерней

11

Ви можете перевірити необов’язково переданий прапор із параметрами дії store_trueта store_falseаргументації:

import argparse

argparser = argparse.ArgumentParser()
argparser.add_argument('-flag', dest='flag_exists', action='store_true')

print argparser.parse_args([])
# Namespace(flag_exists=False)
print argparser.parse_args(['-flag'])
# Namespace(flag_exists=True)

Таким чином, вам не доведеться турбуватися про перевірку умовно is not None. Ви просто перевірите наявність Trueабо False. Детальніше про ці параметри читайте в документах тут


1
це не вирішує, чи можна встановити аргумент, який має значення, чи ні. Основна проблема тут полягає в тому, щоб знати, чи значення аргументів походить від defaul = "" або це надається користувачем.
м3нда

5

Якщо ваш аргумент є позиційним (тобто він не має префіксу "-" або "-", а лише аргумент, як правило, ім'я файлу), ви можете використовувати параметр nargs для цього:

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()

if args.filename is not None:
    print('The file name is {}'.format(args.filename))
else:
    print('Oh well ; No args, no problems')

3

Ось моє рішення, щоб дізнатися, чи використовую я змінну argparse

import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-1", "--first", required=True)
ap.add_argument("-2", "--second", required=True)
ap.add_argument("-3", "--third", required=False) 
# Combine all arguments into a list called args
args = vars(ap.parse_args())
if args["third"] is not None:
# do something

Це може дати більше розуміння вищенаведеної відповіді, яку я використав і адаптував для роботи над своєю програмою.


0

Для того, щоб звернутися до коментаря @ kcpr щодо (зараз прийнятої) відповіді від @Honza Osobne

На жаль, він не працює, тоді аргумент визначив значення за замовчуванням.

спершу можна перевірити, чи був наданий аргумент, порівнюючи його з Namespaceоб'єктом abd, що забезпечує default=argparse.SUPPRESSопцію (див. відповіді @ hpaulj та @Erasmus Cedernaes та цей python3 doc ), а якщо він не був наданий, то встановити його за замовчуванням.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--infile', default=argparse.SUPPRESS)
args = parser.parse_args()
if 'infile' in args: 
    # the argument is in the namespace, it's been provided by the user
    # set it to what has been provided
    theinfile = args.infile
    print('argument \'--infile\' was given, set to {}'.format(theinfile))
else:
    # the argument isn't in the namespace
    # set it to a default value
    theinfile = 'your_default.txt'
    print('argument \'--infile\' was not given, set to default {}'.format(theinfile))

Використання

$ python3 testargparse_so.py
argument '--infile' was not given, set to default your_default.txt

$ python3 testargparse_so.py --infile user_file.txt
argument '--infile' was given, set to user_file.txt

0

Дуже просто, після визначення змінної аргументів 'args = parser.parse_args ()' вона містить усі дані змінних підмножини аргументів. Щоб перевірити, чи встановлена ​​змінна чи ні, припускаючи, що використовується 'action = "store_true" ...

if args.argument_name:
   # do something
else:
   # do something else
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.