首页 > 解决方案 > 如果默认值或给定值,则 ArgParse 参数错误无

问题描述

在为我的程序解析参数时,如果未指定为程序的参数,我还希望能够从环境中获取某些参数。

我目前有:

parser = argparse.ArgumentParser(
    description="Foo Bar Baz")
parser.add_argument('--metadata-api-user', type=str,
                    help='Username for basic authentication access to the metadata API. If not given, will be extracted from env variable {}'.format("API_USER"),
                    default=os.environ.get("API_USER"))
parser.add_argument('--metadata-api-password', type=str,
                    help='Password for basic authentication access to the metadata API. If not given, will be extracted from env variable {}'.format("API_PASS"),
                    default=os.environ.get("API_PASS"))
parser.add_argument('--version', type=int, help='Version number', default=1)
parser.add_argument('--location', type=str, help='Location to place thing (default: ./)',default="./")

args = parser.parse_args(args)

这提供了我想要的功能,但是如果未给出 env 变量并且未命令行中给出它们,我希望 argparse 引发 ArgumentError。

如果仅在命令行上而不是在 env 变量中指定,则 environ[keyname] 在创建参数时会引发 keyerror,这不是很好。

在创建参数时,像 'allow-none'=false 这样的参数会很棒,但是如果有人知道另一种解决方案,那就太棒了。

标签: python-2.7argparse

解决方案


default如果用户没有提供给定值,它将简单地返回给定值,但是它有一个特殊情况 forNone和 for 字符串。

传递Nonedefault将短路并返回None

将字符串传递给将使用构造函数default返回解析的字符串。type

我实现了一个名为 的自定义参数化类型not_none,它将尝试使用给定的类型构造函数解析字符串,或者如果字符串为空,则会大声失败。

import argparse
from os import environ
from typing import Callable, TypeVar
T = TypeVar('T')

def not_none(type_constructor: Callable[[str], T] = str):
    """Convert a string to a type T."""
    def parse(s: str) -> T:
        """argparse will call this function if `s` is an empty string, but not when `s` is None."""
        if not s:
            raise ValueError
        else:
            return type_constructor(s)
    return parse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--foo', help="A foo...", type=not_none(int), default='1')
    parser.add_argument('--bar', help="A bar...", type=not_none(), default=environ.get('BAR', ''))
    # args = parser.parse_args(['--foo', '1'])
    args = parser.parse_args(['--bar', 'BAR'])
    print(args.foo, args.bar)

推荐阅读