1

I have a Python script that gets two user inputs as command line arguments. The first user input is called load-class and the second call-method.

The main Python script acts as an - so called - controller which loads other (lets call them controller cases) Python scripts, calls methods within those scripts and does something with the method returns. This is why the operator cannot execute the controller cases Python scripts directly.

Here is the non-working example:

#!/usr/bin/env python

import sys
import argparse
import textwrap

import ControllerCases

parser = argparse.ArgumentParser(
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="{0}".format('-' * 80),
    description=textwrap.dedent('''\
    TODO: Enter Title Here
{0}
  TODO: Enter Info Here
{0}
'''.format('-' * 80))
)

parser.add_argument('--load-class', '-c', type=str, required=True, help="Name of the class.")
parser.add_argument('--call-method',  '-m', type=str, required=True, help="Name of the method within selected class.")

parsed_args = parser.parse_args()

def main(argv):
    print 'Number of arguments:', len(sys.argv), 'arguments.'
    print 'Argument List:', str(sys.argv)
    print 'Load class: ', str(parsed_args.load_class)
    print 'Call method: ',  str(parsed_args.call_method)
    getattr(ControllerCases[parsed_args.load_class], parsed_args.call_method)(argv)

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

The controller cases Python scripts looking like this:

#!/usr/bin/env python

class dummy():
    def hello(argv):
        print 'Hello World'

Within the ControllerCases folder I have a __init__.py:

#!/usr/bin/env python

import os
for module in os.listdir(os.path.dirname(__file__)):
    if module == '__init__.py' or module[-3:] != '.py':
        continue
    __import__(module[:-3], locals(), globals())
del module

Now I have tried to execute the controller and this happened:

$ python controller.py --load-class dummy --call-method hello
Number of arguments: 5 arguments.
Argument List: ['controller.py', '--load-class', 'dummy', '--call-method', 'hello']
Load class:  dummy
Call method:  hello
Traceback (most recent call last):
  File "controller.py", line 33, in <module>
    main(sys.argv[1:])
  File "controller.py", line 30, in main
    getattr(ControllerCases[parsed_args.load_class], parsed_args.call_method)(argv)
TypeError: 'module' object has no attribute '__getitem__'

I am using Python 2.7.13.

How to dynamically load class and call method in Python?

1 Answer 1

1

I have solved it by little real life help. I had to convert the controller cases from class to module and had to call getattr twice: Once for the module and once for the method.


Convert the controller case class into an controller case module by removing the class XYZ(): line.

From:

#!/usr/bin/env python

class dummy():
    def hello(argv):
        print 'Hello World'

To:

#!/usr/bin/env python

def hello(argv):
    print 'Hello World'

Change the getattr code in the controller.

From:

def main(argv):
    print 'Number of arguments:', len(sys.argv), 'arguments.'
    print 'Argument List:', str(sys.argv)
    print 'Load class: ', str(parsed_args.load_class)
    print 'Call method: ',  str(parsed_args.call_method)
    getattr(ControllerCases[parsed_args.load_class], parsed_args.call_method)(argv)

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

To:

def main(argv):
    print 'Number of arguments:', len(sys.argv), 'arguments.'
    print 'Argument List:', str(sys.argv)
    print 'Load class: ', str(parsed_args.load_class)
    print 'Call method: ',  str(parsed_args.call_method)
    load_class = getattr(ControllerCases, parsed_args.load_class)
    call_method = getattr(load_class, parsed_args.call_method)
    try:
        call_method(argv)
    except KeyboardInterrupt:
        print 'UserAborted'

if __name__ == "__main__":
    main(sys.argv[1:])
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.