Python преобразует словарь в argparse

#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 и добавление их в ваш синтаксический анализатор будет работать, хотя вы не можете знать описание и т. Д.