Jessi Jessi - 1 month ago 22
Python Question

python argparse in separate function inside a class and calling args from init

I have a question regarding passing args to variables inside init

Here are my working version of code.

class A:
def __init__(self):
self.id = args.id
self.pw = args.pw
self.endpoint = args.endpoint

def B:
..do something..

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--id', type=str, help = 'username')
parser.add_argument('-p', '--pw', type=str, help ='password')
parser.add_argument('-e', '--end_point', type=str , help='end point of api')
args = parser.parse_args()


The above code works, but what I am trying right now is to put all the argparse codes inside a function inside class A and assign arg to init.
I looked in the web and I couldn't find a good solution.

class A:
def __init__(self):
self.id = self.parse_args(id)
self.pw = self.parse_args(pw)
self.endpoint = self.parse_args(endpoint)

def B:
..do something..

def parse_args(self,args):
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--id', type=str, help = 'username')
parser.add_argument('-p', '--pw', type=str, help ='password')
parser.add_argument('-e', '--end_point', type=str , help='end point of api')
return parser.parse_args(args)


Ok, so to be exact, I'm not sure how I should approach this problem.

In above example, I just called args.variable for args to work but in this case I call self.id = self.parse_args.id?

parse_args function return args and I also tried self.id = self.parse_args(id) and this is giving me

TypeError: 'builtin_function_or_method' object is not iterable


The part of reason why I want to separate args into a separate function is to simplify my unit test with argparse.

Any help will be appreciated.

Answer

So in the first case, you must be doing

if __name__ ...
....
args = parser.parse_args()
a = A()

The A.__init__ can see args because it is global.

I'm don't see why you'd want to make the argparse code part of A; you don't want it to run every time you use A() do you? You could only make one set of values.

I think it would be test to make the parse_args code a method, that can be run, at will, after creating the class.

Here's an approach that has, I think, pretty good flexibility:

import argparse

class A:
  def __init__(self, id=None, pw=None, endpoint=None):
      self.id = id
      self.pw = pw
      self.endpoint = endpoint

  def parse_args(self, argv=None):
      parser = argparse.ArgumentParser()
      parser.add_argument('-i', '--id', type=str, help = 'username')
      parser.add_argument('-p', '--pw', type=str, help ='password')
      parser.add_argument('-e', '--end_point', type=str , help='end point of api')
      args = parser.parse_args(argv)
      self.id = args.id
      self.pw = args.pw
      self.endpoint = args.end_point

  def __str__(self):
      return 'A(%s,...)'%self.id

if __name__ == "__main__":
    a = A()
    print(a)
    a.parse_args()
    print(a)
    b = A(id='you')
    print(b)
    b.parse_args(['--id','me'])
    print(b)

Values can be set during object creation, from commandline or from custom argv

1610:~/mypy$ python stack39967787.py --id joe
A(None,...)
A(joe,...)
A(you,...)
A(me,...)

==================

My 1st method (temporarily deleted)

class A():
    def __init__(self):
        args = self.parse_args()
        self.a = args.a
        etc
    @static_method
    def parse_args(self):
        parser = ....
        return parser.parse_args()

=====================

Your class A could be used as Namespace, letting parse_args update the artributes directly (it uses setattr.

import argparse
class A:
  def __init__(self, id=None, pw=None, endpoint=None):
      self.id = id
      self.pw = pw
      self.endpoint = endpoint

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--id', type=str, help = 'username')
    parser.add_argument('-p', '--pw', type=str, help ='password')
    parser.add_argument('-e', '--endpoint', type=str , help='end point of api')
    args = parser.parse_args()
    print(args)

    a = A()
    parser.parse_args(namespace=a)
    print(vars(a))

producing:

1719:~/mypy$ python stack39967787_1.py --id joe --pw=xxxx -e1
Namespace(endpoint='1', id='joe', pw='xxxx')
{'endpoint': '1', 'id': 'joe', 'pw': 'xxxx'}