使用 argparse 时将环境变量的选项设置为位置参数

Setting options from environment variables to positional arguments when using argparse

我有一个使用 argparse 和位置参数的小程序。我试图通过使用环境变量来设置该参数,但无法正常工作。

我看过这个 post: Setting options from environment variables when using 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

哪个returns这个:

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

您需要将位置参数设为可选,尝试 nargs='?':

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

请注意,输出略有变化:

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

注意: 有一个副作用 - 它不会 return 错误,即使没有设置 env 变量。

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 属性的测试发生在此位置测试之后,因此像您的 Action 那样更改它并没有帮助。

使位置可选的唯一方法是 nargs - ?要么 *。一个空的字符串列表匹配那些,所以这样的位置总是被消耗。 检查这些文档。 const 参数可能有用。

最新版本放弃了 if positionals 测试,仅使用 required 测试生成未使用的参数列表。您的特殊操作可能适用于该代码。