patternpythonMinor
Simplifying parsing command-line arguments
Viewed 0 times
argumentslineparsingsimplifyingcommand
Problem
I'm currently working on a command-line "database migration" utility. Here are some of the requirements regarding reading the command-line arguments part:
My Solution
Here is what I came up with:
I'm using
```
import argparse
import getpass
def parse_arguments(args):
"""Parses command-line arguments."""
parser = argparse.ArgumentParser()
# general database connection settings
parser.add_argument('-H', '--host', help="Database host IP address", required=True)
parser.add_argument('-D', '--database', help="Database name", required=True)
parser.add_argument('-P', '--port', help="Database port", required=True, type=int)
parser.add_argument('-u', '--user', help='Database user name', required=True)
# modes
parser.add_argument('--validate', help='Enables "validate only" mode', action='store_true')
parser.add_argument('--apply', help='Enables "apply" mode', action='store_true')
# extra settings
parser.add_argument('-b', '--batch-size', help='Batch size - determines how many cases are processed at a time',
type=int, default=5000)
parser.add
- It should accept regular database connection parameters: host, database name, port, user and password (do not allow to specify password as a command-line argument, ask for password separately)
- It works in two modes - "validate" and "apply" - one of them has to be specified explicitly, both cannot be specified
- There should be an integer "batch size" argument specified
- There can be an optional range of integer ids specified via
--id-beginand--id-end(the beginning of the range defaults to1if not specified)
- Instead of a range, there can also be a
--nameargument specified
- Both name and id range cannot be present
- There should be a "verbose" flag
My Solution
Here is what I came up with:
I'm using
argparse module and extracted the parsing command-line arguments into a separate .parse_args() function which returns the parsed arguments (which is argparse.Namespace instance):```
import argparse
import getpass
def parse_arguments(args):
"""Parses command-line arguments."""
parser = argparse.ArgumentParser()
# general database connection settings
parser.add_argument('-H', '--host', help="Database host IP address", required=True)
parser.add_argument('-D', '--database', help="Database name", required=True)
parser.add_argument('-P', '--port', help="Database port", required=True, type=int)
parser.add_argument('-u', '--user', help='Database user name', required=True)
# modes
parser.add_argument('--validate', help='Enables "validate only" mode', action='store_true')
parser.add_argument('--apply', help='Enables "apply" mode', action='store_true')
# extra settings
parser.add_argument('-b', '--batch-size', help='Batch size - determines how many cases are processed at a time',
type=int, default=5000)
parser.add
Solution
Your function should have
For your mutual exclusive options you should use...mutual exclusive groups. However, this only works properly for your mode, because adding a group of not mutually exclusive options (your
With the above code, you can remove all checking you currently do on the modes. It requires that exactly one of the modes is activated.
Also note that the default behavior of
args=None as default. This way you can use it to parse the command-line arguments as well as pass in a list of arguments to parse.For your mutual exclusive options you should use...mutual exclusive groups. However, this only works properly for your mode, because adding a group of not mutually exclusive options (your
--id-begin and --id-end) to a mutually exclusive group seems to no be supported at the moment, even though there was some activity on that a few years back: http://bugs.python.org/issue10984# modes
action = parser.add_mutually_exclusive_group(required=True)
action.add_argument(
'--validate', help='Enables "validate only" mode', action='store_true')
action.add_argument(
'--apply', help='Enables "apply" mode', action='store_true')With the above code, you can remove all checking you currently do on the modes. It requires that exactly one of the modes is activated.
Also note that the default behavior of
action='store_true' is to have default=False, so you can just do:parser.add_argument('--verbose', help='Enables "verbose" reporting mode',
action='store_true')Code Snippets
# modes
action = parser.add_mutually_exclusive_group(required=True)
action.add_argument(
'--validate', help='Enables "validate only" mode', action='store_true')
action.add_argument(
'--apply', help='Enables "apply" mode', action='store_true')parser.add_argument('--verbose', help='Enables "verbose" reporting mode',
action='store_true')Context
StackExchange Code Review Q#157747, answer score: 4
Revisions (0)
No revisions yet.