#python #dictionary #argparse
Вопрос:
Прямо сейчас у меня есть скрипт, который может принимать аргументы командной строки с помощью argparse. Например, вот так:
#foo.py
def function_with_args(optional_args=None):
parser = argparse.ArgumentParser()
# add some arguments
args = parser.parse_args(optional_args)
# do something with args
Однако я хотел бы иметь возможность использовать эту функцию со словарем вместо этого, например, с чем-то вроде этого:
def function_using_dict(**kwargs):
# define parser and add some arguments
args = parser.parse_dict_args(kwargs)
# everything else is the same
Обратите внимание, что у меня есть много аргументов со значениями по умолчанию в argparse, которые я хотел бы использовать, поэтому следующее не сработает:
def function_no_default_args(**kwargs):
args = kwargs # not using default values that we add to the parser!
Комментарии:
1. Вы просто хотите ввести набор значений в
Namespace
объект? Вы можете сделать это напрямую:args = argparse.Namespace(**kwargs)
. Смыслparse_args
в том, чтобы преобразовать список строк вNamespace
объект; неясно, что у васdict
есть или что вы хотелиargparse
бы с ним сделать в противном случае.2. Это было бы хорошей идеей. Есть ли способ получить значения по умолчанию тоже с помощью синтаксического анализатора, что-то вроде
ns = parser.parse_args([]); ns.update(kwargs)
? (но проблема в том, что пространство имен, похоже, не имеет функции «обновить»)3. Вы можете это сделать
parser.parse_args([], ns)
, хотяparse_args
и не будете принимать во внимание значения, которые ужеns
есть . Если вы хотите , чтобы вашkwargs
приоритет был вышеparse_args
, вы можете сделать что-то вродеn = Namespace(**{ **vars(p.parse_args([])), **kwargs})
.
Ответ №1:
argparse.Namespace
это относительно простой подкласс объектов, большая часть кода которого посвящена отображению атрибутов (как print(args)
показано на рисунке). Внутренне parse_args
использует get_attr
пространство имен и set_attr
для доступа к нему, сводя к минимуму предположения об именах атрибутов.
При использовании подпараметров подпараметр начинается с «пустого» пространства имен и использует следующий код для копирования своих значений в основное пространство имен.
# In case this subparser defines new defaults, we parse them
# in a new namespace object and then update the original
# namespace for the relevant parts.
subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
for key, value in vars(subnamespace).items():
setattr(namespace, key, value)
Первоначально основное пространство имен было передано подразделу, например parser.parse_known_args(arg_strings, namespace)
, но текущая версия позволяет подразделу по умолчанию иметь приоритет.
Обработка значений по умолчанию немного сложна. Если у вас нет никаких необходимых аргументов, то
args = parser.parse_args([])
установит все значения по умолчанию. Или вы можете посмотреть в начале parse.parse_known_args
, чтобы увидеть, как значения по умолчанию вставляются в пространство имен в начале синтаксического анализа. Просто имейте в виду, что в конце разбора есть дополнительный шаг, который запускает оставшиеся значения по умолчанию через соответствующие type
функции.
Ответ №2:
Если вы пытаетесь преобразовать результат parse_args
в a dict
, вы, вероятно, можете просто сделать это:
kwargs = vars(args)
После вашего комментария я задумался об этом. Перейдем к вашей существующей функции.
#foo.py
def function_with_args_and_default_kwargs(optional_args=None, **kwargs):
parser = argparse.ArgumentParser()
# add some arguments
# add the other arguments
for k, v in kwargs.items():
parser.add_argument('--' k, default=v)
args = parser.parse_args(optional_args)
# do something with args
Комментарии:
1. Привет, Бен, спасибо за быстрый ответ. Я хотел сделать все наоборот. У меня есть словарь, но я все еще хочу иметь возможность «анализировать» его с помощью argparse, чтобы я также мог получать аргументы со значениями по умолчанию.
2. Вам не нужны описания, или вы просто хотите, чтобы аргументы (при условии, что все строки) имели значение по умолчанию?
3. Вы правы, в этом случае мне не нужны описания argparse для моих аргументов. Я просто хочу, чтобы они имели значение по умолчанию, которое я уже указал с помощью argparse.
4. Пришлось сделать несколько исправлений, но я думаю, что повторение
kwargs
и добавление их в ваш синтаксический анализатор будет работать, хотя вы не можете знать описание и т. Д.