2

I'm writing a module that can be accessed from an import directly as well as from the command line using argparse. How can I allow my functions to work for both argparse and general module imports? Argparse requires me to use something like:

import argparse 

def foo(args):
  arg1 = args.arg1
  arg2 = args.arg2

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  subparsers = parser.add_subparsers()

  parser_foo = subparsers.add_parser('foo')
  parser_foo.add_argument('arg1')
  parser_foo.add_argument('arg2')
  parser_foo.set_defaults(func=foo)
  args = parser.parse_args()
  args.func(args)

But if I import this module, I cannot just input one argument "args" for everything.

I thought of using just **kwargs to receive the arguments (passing the argparse arguments as vars(**args)), but I'm not sure if this is good practice.

def foo(**kwargs):
  arguments = {
    arg1 = None,
    arg2 = None,
  }
  arguments.update(**kwargs)

  arg1 = arguments['arg1']
  arg2 = arguments['arg2']

Then, every time I use the functions from the imported module I have to use key worded arguments.

foo(arg1='value1',arg2='value2')

What would be a better way to approach this?

Is there a way to pass positional arguments using argparse? So when the module is imported, one can do

foo('value1','value2')

EDIT

I thought of another possible solution

def foo(arg1=None,arg2=None):
  pass

This way the function would accept both kwargs and args. Good/bad practice?

cap
  • 365
  • 2
  • 14

1 Answers1

1

You can use vars() to get a dictionary from your Namespace. Here is a simple example:

import argparse


def introduce(name, age):
    print '{} is {} years old'.format(name, age)


def handle_parameters():
    parser = argparse.ArgumentParser()
    parser.add_argument('name', type=str)
    parser.add_argument('age', type=int)
    return parser.parse_args()


def main():
    args = handle_parameters()

    introduce(**vars(args))
    introduce('john', 10)


if __name__ == '__main__':
    main()

If you have a lot of arguments or if you don't like this solution you can create your own Namespace and pass only one argument (the namespace) to your function as described in this post.

Hope it helps.

Michael
  • 539
  • 6
  • 12