带环境变量的argparse
envargparse的Python项目详细描述
带环境变量的argparse。这个模块都是派生的argparse 类支持环境变量和一个框架或一组建议的 扩展argparse的增强功能。
示例
以下内容摘自本模块末尾的条件:
parser = EnvArgParser\ ( prog="Test Program" , formatter_class=EnvArgDefaultsHelpFormatter ) parser.add_argument\ ( '--bar' , required=True , env_var="BAR" , type=int , nargs="+" , default=22 , help="Help message for bar." ) parser.add_argument\ ( 'baz' , type=int ) args = parser.parse_args() print(args)
示例输出:
$ BAR="1 2 3 '45 ' 6 7" ./envargparse.py 123 Namespace(bar=[1, 2, 3, 45, 6, 7], baz=123)
$ ./envargparse.py -h usage: Test Program [-h] --bar BAR [BAR ...] baz positional arguments: baz optional arguments: -h, --help show this help message and exit --bar BAR [BAR ...] Help message for bar. (default: 22) (env_var: BAR)
工作原理
这个模块试图变得非常简单:它可能看起来更长,因为它有很好的注释。没有代码重复。实际上,版本0.1(标记)更简单:通过parse_args()的命名空间参数跟踪操作,保持优先级:
cmd args > env var > preexisting namespace > defaults<>基本上,它存储在命名空间内,如果环境变量存在,每个动作都有一个环境变量密钥的唯一实例。在argparse完成解析之后,它将执行与每个剩余的唯一实例相关联的操作。想法是这样的:如果操作是通过命令行提供的,那么它将从命名空间中被覆盖。
如果需要,您仍然可以使用该版本,但它不处理未能在命名空间上设置dest属性的操作。公平地说,这样的行动是极不可能的。有一段时间,我为每个动作考虑了沙空拳空洞命名空间,只将
版本0.2(标记)是围绕跟踪操作构建的。是否已将操作视为命令行参数,以及调用操作的频率。信不信由你,有些边缘的情况下,一个行动可以看到,但没有调用。有关详细信息,请参见注释。
envargparser类维护所看到的操作集,而每个操作(不管是否环境变量键)都嵌入在跟踪对象中。最初是解析函数中的函数局部变量,看到的操作集被提升到实例命名空间中,并在每次新的解析过程之前重置。幸运的是,在看到一个操作和调用\u get_values之间有一个1:1的调用对应关系,它现在更新看到的操作集。每次调用时,每个跟踪对象都会增加一个计数器,否则其行为与包含的操作完全相同,转发(几乎)所有属性访问。
一个环境变量记录,
至于实际解析环境变量,在0.1到0.2之间没有太大的变化。由于每个操作都可以重写解析函数,因此默认的env var_parse是一个静态方法;第一个参数始终是解析器。默认值通过依赖内部的ArgumentParser方法模拟对ArgParse的解析(计算、转换和检查值),而不需要代码复制。其实很简单-只需要两个方法调用。参数是使用shlex拆分的,但是您的自定义解析器可以使用yaml、json或您喜欢的任何其他方法。不管是什么情况,解析函数都必须返回一个元组:结果值和一个额外值列表。由于额外的值通常会引发异常,您可以考虑将其保留为空。
基本上就是这样,除了值检查模板。从python 3.7开始,新引入的混合解析方法执行两步解析,强制envargparser跟踪解析“深度”。所看到的操作集仅在此两个过程之前被清除,环境变量仅在之后被解析-bo在最深处。
有一个将环境变量键添加到参数帮助的帮助格式化程序,以及一个将环境变量键和参数默认值都添加到类中的示例mix withargparse.argumentDefaultShelpFormatter。自定义帮助格式化程序只需从适当的基类继承即可创建。
接下来要做的只是锦上添花。虽然这个模块并没有实际使用它,也没有更改默认行为,但它是一个很好的展示,展示了什么是可能的,也许对用户定义的派生类是有用的。
原始的argumentparser是相对单一的,而envargparser则使用action和parser之间的协作oop来允许parser方法的每个action重写。虽然解析器通常会调用自己的方法,但现在它会调用到操作中。默认情况下,该操作从解析器的基类调用匹配方法,因此开箱即用没有行为更改。作为概念证明,这只适用于\u get_values和get_values但如果有用,可以通过自定义的\u getattribute_uu扩展到所有方法。同时,可以添加其他方法,或者通过从envargparser和envargaction派生来重写默认行为。
建议
让我们退后一点。为什么不能使用参数默认值:
import argparse import os parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("--foo", default=os.environ.get("FOO","bar"), help="FOO!") parser.parse_args()
在默认值和环境之间创建一个人工依赖项。换句话说,这不是用户所期望的。注意默认值是如何保持不变的:
$ ./test.py -h usage: test.py [-h] [--foo FOO] optional arguments: -h, --help show this help message and exit --foo FOO FOO! (default: bar)
$ FOO=456 ./test.py -h usage: test.py [-h] [--foo FOO] optional arguments: -h, --help show this help message and exit --foo FOO FOO! (default: 456)
不幸的是,argparse太黑了,无法对其进行干净的修改,因此该模块充当了建议改进的工作路线图。要点:
对解析更加透明。
在实例名称空间中维护解析状态,例如所看到的操作集,而不是作为不可访问的方法变量。在多级解析期间跟踪解析深度。让基础动作类跟踪它被调用的频率。将核心解析方法标记为公共api的一部分。
使解析更加模块化。
为以下对象创建可重用的入口点(方法):
- 正在分析单个可选参数。
- 正在分析单个位置参数。
- 基于参数值检查冲突。
- 处理异常(作为装饰器)。
现在代码太单一了。
不要强制每个参数使用相同的解析链。
允许操作重载重要的解析器方法,如\u get\u values,\u get\u values或.u match\u参数。
更重要的是:
切换到新样式({})字符串格式。
旧样式(%)字符串格式无法访问对象属性。\u get\u help\u string方法应返回一个格式字符串,该字符串将无法访问envargrecord的属性。
模块
代码注释很好,下面是提供的类的简短列表:
- 环境记录
- envargparser
- 环境作用
- 环境帮助格式化程序
- envargdefaultshelpformatter
- 容器
要求
- Python 3.7+
- module: decorator (@PyPI)
许可证
GPLv3+; see LICENSE.txt