0

I want to implement a python3 command line by argparse, which supports positional arguments and flag options.

For example:

usage: mycmd [-v] [-h] [-o] text

mycmd text       print text
mycmd -h         show help message and exit
mycmd -v         show version info
mycmd -o text    print text and dump text to file mycmd.txt

Here's my implementation:

import argparse

class MyCmd:
  def __init__(self):
    self.parser = argparse.ArgumentParser()
    self.parser.add_argument('text', help='print text')  # mycmd text
    self.parser.add_argument('-v', action='store_true', dest='version', help='show version info') # mycmd -v
    self.parser.add_argument('-o', dest='output', help='print text and dump text to file mycmd.txt')
  def parse(self):
    return self.parser.parse_args()
  def text(self, text):
    print(text)
  def version(self):
    print('version info: mycmd-0.0.1')
  def output(self, text):
    print(text)
    fp = open('mycmd.txt', 'w')
    fp.write(text + '\n')
    fp.close()

if __name__=='__main__':
  mycmd = MyCmd()
  (options, args) = mycmd.parse()
  if options.text is not None:
    mycmd.text(text)
  elif options.version is not None:
    mycmd.version()
  elif options.output is not None:
    mycmd.output(options.output)

When I test it with:

$ ./mycmd -v

Gives me error:

usage: mycmd [-h] [-o OUTPUT]
            [-v]
            text
mycmd: error: the following arguments are required: text

Why mycmd cannot consume mycmd -v ?

2
  • you didn't provide a text argument. Commented Apr 30, 2020 at 15:17
  • Using '-v' does not keep it from trying to parse all arguments, and raising an error when a required one is missing. But there is a 'version' action class that will print a value and exit before doing the rest of the parsing. Commented Apr 30, 2020 at 15:41

1 Answer 1

1

What your original implementation is missing is the step of including a specific subparse to the text processing flow.

Here's a more simplified version (without a class):

import argparse


def version():
    return 'v0.0.1'

def print_and_save(text, file_path):
    print(text)
    if file_path:
        with open(file_path, 'w') as fp:
            fp.write(text + '\n')
            fp.close()


if __name__=='__main__':
    # Root (rt)
    root_parser = argparse.ArgumentParser()
    root_parser.add_argument('-v', '--version', action='store_true', help='show version info')

    root_sbparsers = root_parser.add_subparsers(help='sub-command help')

    # Adding sub-commands
    text_parser = root_sbparsers.add_parser('process', help='print text')
    text_parser.add_argument('text', type=str, help='text you want to work with')
    text_parser.add_argument('-o', type=str, default=None, help='print text and dump text to file mycmd.txt')

    args = root_parser.parse_args()

    if args.version:
        print(version())
    elif args.text:
        print_and_save(args.text, args.o)

I'm not sure why you have to embed it on a whole class but here's the version with it:

import argparse

class MyCmd(object):
    def __init__(self):
        # Root (rt)
        self.parser = argparse.ArgumentParser()
        self.parser.add_argument('-v', '--version', action='store_true', help='show version info')

        root_sbparsers = self.parser.add_subparsers(help='sub-command help')

        # Adding sub-commands
        text_parser = root_sbparsers.add_parser('process', help='print text')
        text_parser.add_argument('text', type=str, help='text you want to work with')
        text_parser.add_argument('-o', type=str, default=None, help='print text and dump text to file mycmd.txt')

    def parse(self):
        return self.parser.parse_args()

    def text(self, text):
        print(text)

    def version(self):
        print('version info: mycmd-0.0.1')

    def output(self, text, file_path):
        with open(file_path, 'w') as fp:
            fp.write(text + '\n')
            fp.close()


if __name__=='__main__':
    mycmd = MyCmd()
    args = mycmd.parse()

    if args.version:
        mycmd.version()
    elif args.text:
        mycmd.text(args.text)
        if args.o:
            mycmd.output(args.text, args.o)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.