argparse more likely is the one of frequently used Python's libraries. It covers all standard cases out of the box. When a case goes beyond the box a developer is encouraged to extend the library with the specially provided API.
What to do when the argument is marked as required and its value is not changed during some quite long time? Make the argument's value persistent; store somewhere. Otherwise your application more likely has all chances to be recognized as unfriendly by an end-user. You may want to store a value of the argument somewhere in a configuration file. But what the file format should be? How to organize the file? Where should it be located? The are more questions than answers.
Why not to be able to pass the arguments to argparse's parser through the system environment? Such approach is widely recognized and makes your application easily scriptable.
When an argument is marked as optional a value from the system environment could be accessed by evaluating a default one:
Or in a bit complicated way when the value is not allowed to be empty:
Due to the design mandatory arguments in argparse library are not allowed to have default values.
There is an interface in argparse called Action which is associated with the argument being processed. The interface is intended to customize the way how an argument is processed/stored. Providing own implementation of the interface will allow you to look the desired value of the argument in system environment:
When the argument's value is found in the system environment variable scope, the built-in options in **kwargs are patched:
What to do when the argument is marked as required and its value is not changed during some quite long time? Make the argument's value persistent; store somewhere. Otherwise your application more likely has all chances to be recognized as unfriendly by an end-user. You may want to store a value of the argument somewhere in a configuration file. But what the file format should be? How to organize the file? Where should it be located? The are more questions than answers.
Why not to be able to pass the arguments to argparse's parser through the system environment? Such approach is widely recognized and makes your application easily scriptable.
Optional Arguments
When an argument is marked as optional a value from the system environment could be accessed by evaluating a default one:
parser.add_argument("-c", "--crt", type = str, default = os.environ.get("X509_CRT"), required = False, help = "Path to X509 Certificate")
Or in a bit complicated way when the value is not allowed to be empty:
parser.add_argument("-c", "--crt", type = str, default = os.environ.get("X509_CRT") or "~/.work/vpn.crt", required = False, help = "Path to X509 Certificate")
Required Arguments
Due to the design mandatory arguments in argparse library are not allowed to have default values.
There is an interface in argparse called Action which is associated with the argument being processed. The interface is intended to customize the way how an argument is processed/stored. Providing own implementation of the interface will allow you to look the desired value of the argument in system environment:
class FindValueInEnvironmentAction(argparse.Action): def __init__(self, varName, **kwargs): assert kwargs.get("required") valueFromEnv = os.environ.get(varName) requiredValue = True if valueFromEnv: kwargs["required"] = False kwargs["default"] = valueFromEnv argparse.Action.__init__(self, **kwargs) def __call__(self, parser, namespace, values, option_string): setattr(namespace, self.dest, values) ... parser.add_argument("-c", "--crt", type = str, action = FindValueInEnvironmentAction, varName = "X509_CRT", required = True, help = "Path to X509 Certificate")
When the argument's value is found in the system environment variable scope, the built-in options in **kwargs are patched:
- required attribute is removed;
- default value is set to the read one.
These steps allow to pretend that an optional argument with a predefined default value is being processed. Here a value of the argument passed through the command line has a priority over a value set through "X509_CRT" environment variable.
I would also inject to our implementation a dictionary where to look up; it will allow us to cover the class with unit tests. And if you a user of Python3 feel free to try an alternative way.
I would also inject to our implementation a dictionary where to look up; it will allow us to cover the class with unit tests. And if you a user of Python3 feel free to try an alternative way.
This comment has been removed by the author.
ReplyDeleteThis library also does what you want:
ReplyDeletehttps://pypi.python.org/pypi/ConfigArgParse/