Как узнать, действительно ли аргумент argparse указан в командной строке?

Я использую arparse для обновления конфигурации dict, используя значения, указанные в командной строке. Поскольку я хочу обновить только значения в конфигурации, для которых значение было явно указано в командной строке.

поэтому я пытаюсь определить не указанные аргументы, проверяя каждое действие, если getattr(args, action.dest) == action.default или равенство преобразованного типа arg. Затем я обновляю все свои значения в dict, для которого это false.

но это конечно не удается, если я явно указать аргумент в командной строке, который совпадает с моим аргументом по умолчанию. Есть ли возможность идентифицировать эти явно упомянутые аргументы в argparser или у меня есть чтобы определить их вручную в sys.аргв?

спасибо!

Edit:

чтобы сделать мои намерения яснее. У меня есть аргумент, подобный следующему:

parser.add_argument('--test', default='meaningful_default')

и конфигурация типа

config = { 'test' : 'nondefault_val'}

теперь я хочу обновить config только с явно указанными аргументами. Сравнение атрибутов args со значениями по умолчанию работает до тех пор, пока я не укажу что-то вроде prog.py --test meaningful_default чтобы обновить мою конфигурацию снова со значением, которое просто случается также значение по умолчанию

3 ответов


на parser поддерживает seen_actions установить объект во время синтаксического анализа (в _parse_known_args метод). В конце разбора он проверяет этот набор на требуемые аргументы (с required=True), и может выдать ошибку. Вариация также используется с взаимоисключающими группами.

но эта переменная недоступна вне этой функции. Так не хватает какого-то "крючка", который позволяет применять ваши собственные тесты в parse_args действие, ваш лучший вариант-проверить значения по умолчанию. Или вы можете посмотреть sys.argv[1:].

по умолчанию default is None. Это хорошо для этой цели, потому что ваш пользователь не может дать это значение. То есть нет строки, которая преобразуется в None (по крайней мере, не в любой нормальной type методов).

parser.add_argument('--foo') # default=None
...
if args.foo is None:
    # clearly foo has not been specified.
    args.foo = 'the real default'
else:
    # foo was specified
    pass

Если вы предпочитаете использовать argparse и уметь указать значения по умолчанию, есть простое решение с использованием двух анализаторов.

I. определите свой главный парсер и проанализируйте все свои аргументы с правильными значениями по умолчанию:

parser = argparse.ArgumentParser()
parser.add_argument('--test1', default='meaningful_default1')
parser.add_argument('--test2', default='meaningful_default2')
...
args, unparsed = parser.parse_known_args()

II. Определите анализатор aux с помощью argument_default=argparse.SUPPRESS чтобы исключить неопределенные аргументы. Добавьте все аргументы из основного синтаксического анализатора, но без каких-либо значений по умолчанию:

aux_parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
for arg in vars(args): aux_parser.add_argument('--'+arg)
cli_args, _ = aux_parser.parse_known_args()

Это не очень элегантное решение, но хорошо работает с argparse и всеми свои преимущества.


вы можете использовать пользовательское действие, чтобы определить, было ли значение arg по умолчанию или установлено в командной строке:

import argparse

class FooAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        setattr(namespace, self.dest+'_nondefault', True)

parser = argparse.ArgumentParser()
parser.add_argument('--test0', default='meaningful_default', action=FooAction)
parser.add_argument('--test1', default='meaningful_default', action=FooAction)

args = parser.parse_args('--test0 2'.split())

if hasattr(args, 'test0_nondefault'):
    print('argument test0 set on command line')
else:
    print('default value of test0 is used')

if hasattr(args, 'test1_nondefault'):
    print('argument test1 set on command line')
else:
    print('default value of test1 is used')