Установка параметров из переменных среды в позиционные аргументы при использовании argparse

У меня есть небольшая программа, которая использует argparse и позиционный аргумент. Я пытаюсь разрешить этот аргумент с помощью переменной окружения, но не работаю.

Я видел этот пост: установка параметров из переменных окружения при использовании argparse, в котором упоминается та же проблема, но не для позиционных аргументов.

Это код до сих пор:

import argparse
import os

class EnvDefault(argparse.Action):
  def __init__(self, envvar, required=True, default=None, **kwargs):
      if not default and envvar:
          if envvar in os.environ:
              default = os.environ[envvar]
      if required and default:
          required = False
      super(EnvDefault, self).__init__(default=default, required=required, **kwargs)

  def __call__(self, parser, namespace, values, option_string=None):
      setattr(namespace, self.dest, values)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('testvar', help="Test variable", action=EnvDefault, envvar='TEST_VAR')
    parser.add_argument('--othervar', help="Other variable", action='store_true')
    args = parser.parse_args()
    if not args.testvar: exit(parser.print_usage())

    print args.testvar

Который возвращает это:

$ TEST_VAR="bla" ./test.py 
usage: test.py [-h] [--othervar] testvar
test.py: error: too few arguments

2 ответа

Решение

too few Сообщение об ошибке указывает, что у вас есть немного более старая версия Python / argparse. Вот код, который генерирует сообщение. Это происходит в конце разбора:

    # if we didn't use all the Positional objects, there were too few
    # arg strings supplied.
    if positionals:
        self.error(_('too few arguments'))

    # make sure all required actions were present
    for action in self._actions:
        if action.required:
            if action not in seen_actions:
                name = _get_action_name(action)
                self.error(_('argument %s is required') % name)

positionals запускает список всех позиционных аргументов, которые удаляются при сопоставлении со строками аргументов. Так что это тестирование, если таковые не были сопоставлены.

Обратите внимание, что тест required Атрибут появляется после этого позиционного теста, поэтому его изменение, как и ваше действие, не помогает.

Единственный способ сделать позиционный опциональный nargs -? или же *. Пустой список строк соответствует этим, поэтому такой позиционный всегда используется. Проверьте документы для них. const Параметр может быть полезен.

Последняя версия падает, что if positionals проверить, используя только required Тест для создания списка аргументов, которые не были использованы. Ваше специальное действие может работать в этом коде.

Вы должны сделать позиционный аргумент необязательным, попробуйте nargs='?':

...
parser.add_argument('testvar', help="Test variable", action=EnvDefault,
        envvar='TEST_VAR', nargs='?')
...

Обратите внимание, что выходные данные немного изменяются:

$ python test.py
usage: test.py [-h] [--othervar] [testvar]

Примечание: есть один побочный эффект - он не возвращает ошибку, даже если переменная env не установлена.

Другие вопросы по тегам