1

I'm trying to write a Python script to create a CLI command. To make it more readable, I'm creating argparse.ArgumentParser object directly in the class __init__() (not in the '__main__' part of the script as is usually the case in tutorials).

The approach included in the sample code below works but it looks messy.

I wonder whether this would be the correct way to do it or I should do something else. (Sorry for newbie question.)

import argparse

class Command:
    def __init__(self, *args):
        self.parser = argparse.ArgumentParser(usage='command [--first] [--second]', description='This is a sample command')
        self.parser.add_argument('--first', type=str, required=True, help='first argument', dest='first_argument')
        self.parser.add_argument('--second', type=str, required=True, help='second argument', dest='second_argument')
        args = self.parser.parse_args()
        self.first_argument = args.first_argument
        self.second_argument = args.second_argument

    def some_operation(self):
        concatenated_str = self.first_argument + self.second_argument
        return concatenated_str

if __name__ == '__main__':
    command = Command() # creating class instance
    print(command.some_operation())

Putting it in a separate class method in this way doesn't work and produces AttributeError:

# Code above
    def set_params(self):
        args = self.parser.parse_args()
        self.first_argument = args.first_argument
        self.second_argument = args.second_argument
        return self.first_argument, self.second_argument
# Code below
Myklebost
  • 59
  • 8
  • This is a matter of opinion but here goes anyway. Unless you're using setter functions in your class (where you could validate the input) then you should validate **outside** of the class. In other words, make sure that whatever's passed to __init__ is known to be valid. Parsing the CLI *outside* of the class would be best practice IMO – DarkKnight Jan 26 '22 at 11:19
  • @JCaesar I see. You mean something along those lines: https://stackoverflow.com/a/2825580/17645092, right? – Myklebost Jan 26 '22 at 11:53
  • `args=parser.parse_args()` returns a class instance whose attributes are the parsed values. Do you need another class layer? You aren't going to make multiple instances of the parser. – hpaulj Jan 26 '22 at 12:31
  • @hpaulj I'm not sure I fully follow, but there won't be another parser or class layer. In this case there would be only one parser that gathers arguments and then provides it to other class methods in order to carry out tasks (such as - in this extremly simplified version - concatenation of those two arguments). – Myklebost Jan 26 '22 at 13:19
  • What code produces the error, and what's the full traceback? – hpaulj Jan 26 '22 at 16:16
  • Agree with other comments that the argparse stuff should take place outside your class, probably in its own function that returns the "args" namespace object. Then, use "args" to feed arguments to a constructor. BTW, the click library is even nicer than argparse. – cbare Jan 26 '22 at 20:25
  • @hpaulj Thank you for the comment but that code itself doesn't produce an error (at least I'm not seeing one), it was rather a question whether such an approach is considered good practice. – Myklebost Jan 27 '22 at 08:05
  • "this way doesn't work and produces AttributeError"? – hpaulj Jan 27 '22 at 19:55

0 Answers0