当前位置:   article > 正文

python动态加载技术_python 动态加载

python 动态加载

提到python动态加载技术,我们需要聊上几个话题:

1)反射技术

2)模块动态加载importlib

3)  callback(函数名传递)--不完全算是吧动态

反射技术

先说反射技术,所谓反射技术就是指的是在程序的运行状态中,对于任意一个类,都可以知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意方法和属性,增加删除方法和属性。这种动态获取程序信息以及动态调用对象的功能称为反射机制。

步骤:

  1. class Animal:
  2. def __init__(self, name, legs) -> None:
  3. self.name = name
  4. self.legs = legs
  5. def get_legs(self):
  6. return self.legs
  7. def get_name(self):
  8. return self.name
  9. animal = Animal('dog', 4)
  10. print(dir(animal))
  11. ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_legs', 'get_name', 'legs', 'name']

具体一个应用场景,比如我们的testcase来自一个文本的创建的一个测试计划,其中是一个所要执行的测试用例的list

['test_test1', 'test_test2',...]

我们要执行它,比如我的测试实例是test_obj

  1. class T1:
  2. def test_test11(self):
  3. print('test11')
  4. def test_test22(self):
  5. print('test22')
  6. class Test(T1):
  7. def test_test1(self):
  8. print('test1')
  9. def test_test2(self):
  10. print('test2')
  11. test_obj = Test()
  12. for test in [ 'test_test1', 'test_test2', 'test_test11', 'test_test22']:
  13. method = getattr(test_obj, test) # 如果该函数不存在会raise exception
  14. method()
  15. # 可以修改如下
  16. test_obj = Test()
  17. for test in [ 'test_test1', 'test_test2', 'test_test11', 'test_test22']:
  18. method = getattr(test_obj, test, lambda :'donothing') # 如果不存在就运行一个匿名函数,实际就是一个默认值
  19. method()

反射中的setattr等不在本次讨论的范畴。

模块动态加载importlib

动态加载模块,可以用于,当我们已经知道我们的模块名称,在我们的目的是动态加载这些module用于运行;动态加载指在程序运行中,动态的加载模块,而不是在运行之前利用import 或from ... import 的方式加载模块的方式。

应用场景:

      (1) 程序在运行期间才能确定加载的模块。

   (2) 在某种条件下,需要通过模块名字符串进行加载的模块。

  1. #mymodule/mytest.py
  2. def helloworld():
  3. print('hello world')
  4. class MyModule:
  5. def print_hello(self):
  6. print(f'hello from {self.__class__}')
  7. # test.py
  8. import importlib
  9. def import_method1():
  10. """From module"""
  11. module = importlib.import_module('mymodule.mytest')
  12. module.helloworld()
  13. my_module_obj = module.MyModule()
  14. my_module_obj.print_hello()
  15. def import_method2():
  16. """From file path"""
  17. file = 'mymodule/mytest.py'
  18. module_name = 'mytest'
  19. # loading module
  20. spec = importlib.util.spec_from_file_location(module_name, file)
  21. module = importlib.util.module_from_spec(spec)
  22. #execute module
  23. spec.loader.exec_module(module)
  24. # invoke methods
  25. module.helloworld()
  26. my_module = module.MyModule()
  27. my_module.print_hello()

另外一个例子,我们的module中有很多个类,相同的方法,这样我们可以批处理进行调用

  1. # mytest/myfile.py
  2. import sys
  3. class Test1:
  4. def setup(self):
  5. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  6. def teardown(self):
  7. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  8. def run(self):
  9. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  10. class Test2:
  11. def setup(self):
  12. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  13. def teardown(self):
  14. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  15. def run(self):
  16. print(f" {self.__module__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}")
  17. # test.py
  18. import importlib
  19. libs = 'mytest.myfile'
  20. class_names = ['Test1', 'Test2']
  21. methods = ['setup', 'run''teardown', 'hello'] # hello不存在的
  22. my_import = importlib.import_module(libs)
  23. for cls_ in class_names:
  24. Clss = getattr(my_import, cls_) # 获取模块下的类
  25. my_class = Clss() # 实例化
  26. for m in methods:
  27. method = getattr(my_class, m, lambda: "DoNothing") # 获取类方法, 默认lambda为了防止函数不存在
  28. method() # 执行方法
  29. # output
  30. mytest.myfile.Test1.setup
  31. mytest.myfile.Test1.run
  32. mytest.myfile.Test1.teardown
  33. mytest.myfile.Test2.setup
  34. mytest.myfile.Test2.run
  35. mytest.myfile.Test2.teardown

另外一种方式:通过__import__加载

函数原型:__import__(name, globals={}, locals={}, fromlist=[], level=-1)

  参数:name:模块名,包含路径

       globals:全局变量,一般默认,如果设置,可设置globals()

       locals:局部变量,一般默认,如果设置,可设置locals()

     fromlist:导入的模块,及name下的模块名、函数名、类名或者全局变量名。

  返回值:module对象,通过取module得属性获取模块得函数、类或者全局变量等。

  1. # 如上代码,我们下面的方式
  2. d1 = __import__(libs)
  3. for cls_ in class_names:
  4. Clss = getattr(my_import, cls_) # 获取模块下的类
  5. my_class = Clss() # 实例化
  6. for m in methods:
  7. method = getattr(my_class, m, lambda: "DoNothing") # 获取类方法
  8. method() # 执行方法

另外一种方式:通过exec进行,但是不建议用邪恶的exec

  1. import_string = "import mytest.myfile as myfile"
  2. exec(import_string )
  3. t1 = myfile.Test1()
  4. t1.setup()

callback方式(回调)

说到回调不得不提python的函数其实也是一种类型

比如你可以将一个函数名给一个变量

比如最常见的匿名函数

squre = lambda x: x*x

squre(5)

25

那么回调就是我们在执行一个函数时候,另外一个函数作为一个变量传入,以便对在该函数中由系统在符合你设定的条件时自动调用

def my_function(a, b, callback_func):

        ....

        if xxx:

                callback_func(**kwargs)

 这里不给赘述了,仅仅该一个例子,比如我们在实时读取文件的时候进行查找默写匹配的

  1. import time
  2. import re
  3. def follow_file_with_timeout(tailed_file,callback_func, timeout=10):
  4. with open(tailed_file) as file_:
  5. file_.seek(0,2) # Go to the end of file
  6. start_time = time.time()
  7. while time.time() - start_time < timeout:
  8. curr_position = file_.tell()
  9. line = file_.readline()
  10. if not line:
  11. file_.seek(curr_position)
  12. time.sleep(1)
  13. else:
  14. callback_func(line)
  15. def my_search(line):
  16. if line:
  17. matched = re.search('Yourpatternhear', line)
  18. if matched:
  19. print(line)
  20. follow_file_with_timeout('test.txt', my_search)

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号