2

Are there other more efficient ways of validating command line args without external modules and argparse?

import sys
import getopt

argv = sys.argv[1:]
try:
    opts, args = getopt.getopt(argv, "h", ["help", "version", "number="])
except getopt.GetoptError as error:
    print(error)
    exit(1)
if args:
    exit(1)
print(opts)
print(args)

So here's how i would do it, but is it ok? I'm new to python and trying to use as many python features as i can

ccvhd
  • 202
  • 3
  • 10
  • 7
    Look into the argparse module. From https://docs.python.org/3.7/library/getopt.html : "The getopt module is a parser for command line options whose API is designed to be familiar to users of the C getopt() function. Users who are unfamiliar with the C getopt() function or who would like to write less code and get better help and error messages should consider using the argparse module instead." – James Nov 11 '19 at 21:17
  • You really should not be using `getop`, use something higher level and more full-featured, at the very least, `argparse` or even somthing third-party, like [`click`](http://click.palletsprojects.com/en/7.x/) – juanpa.arrivillaga Nov 11 '19 at 21:19
  • external libraries such as [`click`](https://click.palletsprojects.com) and [`docopt`](http://docopt.org) may also be worth looking into. – hiro protagonist Nov 11 '19 at 21:19
  • Gonna throw [`python-fire`](https://github.com/google/python-fire) onto the pile as an option as well. – b_c Nov 11 '19 at 21:20
  • ...and this is why "find or recommend an off-site resource" questions are off-topic. Everybody has their own favourite library. – ChrisGPT was on strike Nov 11 '19 at 21:28
  • 1
    Thanks for editing your question, but _why_ "without argparse"? That's clearly a viable answer that's built into the standard library. We can't help you if we don't understand your constraints. – ChrisGPT was on strike Nov 11 '19 at 21:29
  • @Chris project requirement :/ – ccvhd Nov 11 '19 at 21:31
  • @dhvcc, that's a silly requirement in the vast majority of "real" cases. Is this a homework assignment? What other project requirements haven't you shared with us? – ChrisGPT was on strike Nov 11 '19 at 21:32
  • @Chris well it's kind of but the question is just about parsing args without argparse. I'm not the one who made this requirement – ccvhd Nov 11 '19 at 21:34
  • Again, _is this a homework assignment?_ And _are there any other constraints you haven't made us aware of?_ Giving us constraints that don't make sense and hiding details about what you're doing only makes it harder for us to help. It's frustrating for you, for us, and for future users who find this question. – ChrisGPT was on strike Nov 11 '19 at 21:36
  • 1
    Your question is a bit hard to understand, you are basically asking "are there other ways of parsing arguments", but then your requirements reject all other ways... I'm not sure what you are expecting. – juanpa.arrivillaga Nov 11 '19 at 21:37
  • @Chris I told u that it's kind of homework assignment and that these are the only constraints. I understand that i should've gave u the whole story. Anyway the question is now answered – ccvhd Nov 11 '19 at 21:41

2 Answers2

3

You should check out Python's built-in argparse. It takes a lot of the hassle out of manually parsing a complex commands from the command line. You can force certain arguments to be a certain type or value.

Example usage:

import sys
import argparse

PHASES = ['clean', 'package', 'install', 'test', 'deploy']
ALT_PHASES = ['docs', 'demos', 'update']

parser = argparse.ArgumentParser()
parser.add_argument(
    'phase',
    help="the target phase",
    choices=PHASES + ALT_PHASES
)
parser.add_argument(
    '--skip-demos',
    help="skip packaging and deployment of demos",
    action='store_const',
    const=str
)
parser.add_argument(
    '--skip-docs',
    help="skip generation and deployment of user's guide",
    action='store_const',
    const=str
)
parser.add_argument(
    '--skip-tests',
    help="skip tests",
    action='store_const',
    const=str
)
parser.add_argument(
    '--skip-wheels',
    help="skip wheel generation",
    action="store_const",
    const=str
)
parser.add_argument(
    '--update',
    help="update the source code in the virtual environment; do not make the wheels",
    action="store_const",
    const=str
)

def main(args):
    parsed_args = parser.parse_args(args)
    print(parsed_args.phase) # prints the phase


if __name__ == "__main__":
    main(sys.argv[1:])

Example output when entering an invalid argument:

$ python3 build.py hello
usage: build.py [-h] [--skip-demos] [--skip-docs] [--skip-tests]
                [--skip-wheels] [--docs-branch DOCS_BRANCH]
                [--skip-formatting] [--int-tests] [--update]
                {clean,package,install,test,deploy,docs,demos,update}
build.py: error: argument phase: invalid choice: 'hello' (choose from 'clean', 'package', 'install', 'test', 'deploy', 'docs', 'demos', 'update')
mario_sunny
  • 1,412
  • 11
  • 29
1

There are a couple of good libraries in Python to support command-line parsing and argument validation.

I have tried Argparse in the past and it works great. You could refer to this answer to understand how you can use Argparse.

Hope it helps!