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

时间:2015-06-30 13:11:07

标签: python argparse

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

我看过这篇文章: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

返回此内容:

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

2 个答案:

答案 0 :(得分:2)

You need to make positional argument optional, try nargs='?':

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

Note that output changes slightly:

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

Note: There's one side effect - it doesn't return error, even if env variable is not set.

答案 1 :(得分:1)

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测试生成未使用的参数列表。您的特殊操作可能适用于该代码。