Как узнать, действительно ли аргумент 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')