Last active
February 7, 2024 21:56
-
-
Save orls/51525c86ee77a56ad396 to your computer and use it in GitHub Desktop.
Using env vars in argparse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
from EnvDefault import env_default | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser( | |
description="use env vars as defaults for argparse" | |
) | |
parser.add_argument( | |
"--alpha", "-a", | |
action=env_default('ALPHA'), | |
required=False, | |
help="""Optional. Value from CLI will be used if present, or from env var ALPHA. | |
If neither of these is present, value is None becasue no fallback default | |
was given""" | |
) | |
parser.add_argument( | |
"--beta", "-b", | |
action=env_default('BETA'), | |
required=True, | |
help="""Required. Value from CLI will be used if present, or from env var BETA. | |
If neither of these is present, it's an error""" | |
) | |
parser.add_argument( | |
"--gamma", "-g", | |
action=env_default('GAMMA'), | |
required=True, | |
default=9001, | |
help="""Value from CLI will be used if present, or from env var GAMMA. | |
If neither of these is present, default of 9001 is used""" | |
) | |
print parser.parse_args() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Provides a utility to inject environment variables into argparse definitions. | |
Currently requires explicit naming of env vars to check for""" | |
import argparse | |
import os | |
# Courtesy of http://stackoverflow.com/a/10551190 with env-var retrieval fixed | |
class EnvDefault(argparse.Action): | |
"""An argparse action class that auto-sets missing default values from env | |
vars. Defaults to requiring the argument.""" | |
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) | |
# functional sugar for the above | |
def env_default(envvar): | |
def wrapper(**kwargs): | |
return EnvDefault(envvar, **kwargs) | |
return wrapper | |
@flying-sheep that only helps partially. IMHO the correct behavior would be to set the value from environment variable but not to override the default (that can break "help" message when using env vars, which is not broken behavior).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For this to behave as described, the
if not default and envvar:
check needs to be removed.The env variable is supposed to override the default.