【问题标题】:How to dynamically load class and call method in Python?如何在 Python 中动态加载类和调用方法?
【发布时间】:2017-08-05 20:47:32
【问题描述】:

我有一个 Python 脚本,它获取两个用户输入作为命令行参数。第一个用户输入称为load-class,第二个用户输入称为call-method。

主要的 Python 脚本充当 - 所谓的 - 控制器,它加载其他(让我们称之为控制器案例)Python 脚本,调用这些脚本中的方法,并对方法返回做一些事情。这就是为什么操作员不能直接执行控制器用例 Python 脚本的原因。

这是一个无效的例子:

#!/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:])

控制器的 Python 脚本如下所示:

#!/usr/bin/env python

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

在ControllerCases 文件夹中,我有一个__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

现在我尝试执行控制器,结果发生了:

$ 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__'

我使用的是 Python 2.7.13。

如何在Python中动态加载类和调用方法?

【问题讨论】:

    标签: python python-2.7 class methods


    【解决方案1】:

    我已经通过一些现实生活的帮助解决了这个问题。我必须将控制器案例从类转换为模块,并且必须调用 getattr 两次:一次用于模块,一次用于方法。


    通过删除class XYZ(): 行将controller case 类转换为controller case 模块。

    发件人:

    #!/usr/bin/env python
    
    class dummy():
        def hello(argv):
            print 'Hello World'
    

    收件人:

    #!/usr/bin/env python
    
    def hello(argv):
        print 'Hello World'
    

    更改控制器中的getattr代码。

    发件人:

    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:])
    

    收件人:

    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:])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-17
      • 2010-10-07
      • 2010-09-21
      • 1970-01-01
      • 2012-07-20
      • 2019-09-07
      • 1970-01-01
      相关资源
      最近更新 更多