我有一个脚本,它具有某些选项,可以在命令行上传递,也可以从环境变量传递.如果两者都存在,则CLI应该优先,如果两者都没有,则会发生错误.
我可以检查解析后是否分配了该选项,但我更喜欢让argparse执行繁重的工作并负责在解析失败时显示用法语句.
我已经提出了几种替代方法(我将在下面作为答案发布,以便可以单独讨论),但他们觉得我很笨,我认为我错过了一些东西.
是否有一种被接受的"最佳"方式?
(编辑以在未设置CLI选项和环境变量时清除所需的行为)
Chr*_*tts 52
我只是在default使用你想要获取的变量向os.environ的get添加参数时设置变量..get()如果.get()找不到该名称的环境变量,则调用中的第二个参数是默认值.
import argparse
import os
parser = argparse.ArgumentParser(description='test')
parser.add_argument('--url', default=os.environ.get('URL', None))
args = parser.parse_args()
if not args.url:
exit(parser.print_usage())
Run Code Online (Sandbox Code Playgroud)
Rus*_*ing 42
我经常使用这种模式,我已经打包了一个简单的动作类来处理它:
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)
Run Code Online (Sandbox Code Playgroud)
然后我可以从我的代码中调用它:
import argparse
from envdefault import EnvDefault
parser=argparse.ArgumentParser()
parser.add_argument(
"-u", "--url", action=EnvDefault, envvar='URL',
help="Specify the URL to process (can also be specified using URL environment variable)")
args=parser.parse_args()
Run Code Online (Sandbox Code Playgroud)
use*_*965 21
ConfigArgParse将对环境变量的支持添加到argparse中,因此您可以执行以下操作:
p = configargparse.ArgParser()
p.add('-m', '--moo', help='Path of cow', env_var='MOO_PATH')
options = p.parse_args()
Run Code Online (Sandbox Code Playgroud)
wha*_*ier 18
我通常必须为多个参数(身份验证和API密钥)执行此操作..这很简单直接.使用**kwargs.
def environ_or_required(key):
return (
{'default': os.environ.get(key)} if os.environ.get(key)
else {'required': True}
)
parser.add_argument('--thing', **environ_or_required('THING'))
Run Code Online (Sandbox Code Playgroud)
这个话题很老了,但我也遇到了类似的问题,我想我会与你分享我的解决方案。不幸的是,@Russell Heilling 建议的自定义操作解决方案对我不起作用,原因如下:
store_true)default时候(这可以很容易修复)envvaros.environaction或envvar(应该始终是action.dest.upper())这是我的解决方案(Python 3):
class CustomArgumentParser(argparse.ArgumentParser):
class _CustomHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
def _get_help_string(self, action):
help = super()._get_help_string(action)
if action.dest != 'help':
help += ' [env: {}]'.format(action.dest.upper())
return help
def __init__(self, *, formatter_class=_CustomHelpFormatter, **kwargs):
super().__init__(formatter_class=formatter_class, **kwargs)
def _add_action(self, action):
action.default = os.environ.get(action.dest.upper(), action.default)
return super()._add_action(action)
Run Code Online (Sandbox Code Playgroud)
一种选择是检查是否设置了环境变量,并相应地修改对 add_argument 的调用,例如
import argparse
import os
parser=argparse.ArgumentParser()
if 'CVSWEB_URL' in os.environ:
cvsopt = { 'default': os.environ['CVSWEB_URL'] }
else:
cvsopt = { 'required': True }
parser.add_argument(
"-u", "--cvsurl", help="Specify url (overrides CVSWEB_URL environment variable)",
**cvsopt)
args=parser.parse_args()
Run Code Online (Sandbox Code Playgroud)