如果为默认值或给定值,则ArgParse参数错误无

时间:2019-11-19 13:28:36

标签: python-2.7 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]在创建参数时会引发密钥错误。

创建自变量时,像'allow-none'= false这样的东西作为参数很好,但是如果有人知道另一种解决方案,那将很棒。

3 个答案:

答案 0 :(得分:2)

default仅在用户不提供给定值的情况下返回给定值,但是对于None和字符串则有特殊情况。

None传递到default将会短路并返回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)

答案 1 :(得分:1)

不幸的是,我无法找到解决方案,因此我不得不为可以从env变量获取的每个参数添加以下内容:

api_user_action = 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"))

...

if args.metadata_api_user is None:
    raise argparse.ArgumentError(api_user_action,
                                 "API Username was not supplied in either command line or environment variables. \n" + parser.format_help())

这将打印用法和适当的错误消息(如果两者均未提供),但是需要从每个可能适用的参数中进行重复。

答案 2 :(得分:1)

为什么在构建参数时不检查环境变量?

import pyspark.sql.functions as f
from pyspark.sql import Window

w = Window.partitionBy('id', 'date')

df.withColumn('result', f.when(f.col('quantity') == f.min('quantity').over(w), f.col('result'))) \
  .withColumn('result', f.max('result').over(w)).show(10, False)

+---+----------+--------+------+
|id |date      |quantity|result|
+---+----------+--------+------+
|1  |2016-01-02|120     |5     |
|1  |2016-01-01|245     |2     |
|1  |2016-01-01|345     |2     |
|1  |2016-01-01|123     |2     |
|2  |2016-01-02|453     |1     |
|2  |2016-01-01|567     |1     |
|2  |2016-01-01|568     |1     |
+---+----------+--------+------+

这似乎是获得所需结果的最简单方法。