zoukankan      html  css  js  c++  java
  • [Coding笔记] Python装饰器

    官方说明:Python文档 - Decorator
    A function returning another function, usually applied as a function transformation using the @wrapper syntax.

    The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:

    def f(...):
        ...
    f = staticmethod(f)
    
    @staticmethod
    def f(...):
        ...
    

    一个简单的例子:

    import functools
    
    
    def log(func):
        @functools.wraps(func)  # 用于保留函数元信息
        def wrapper(*args, **kwargs):
            print('call %s():' % func.__name__)
            print('args = {}'.format(*args))
            return func(*args, **kwargs)
    
        return wrapper
    

    调用时:

    @log
    def test(p):
        print(test.__name__ + " param: " + p)
        
    test("I'm a param")
    

    输出:
    call test(): args = I'm a param test param: I'm a param

    在实际项目中的用例:

    from functools import wraps
    
    def record_exception_related_info(pause=False):
        """
        记录发生异常时的相关信息,包括:1. 屏幕快照,2. 浏览器控制台日志
        ——注意:浏览器驱动必须作为测试函数所属的类/实例的属性,且命名为driver
        :param pause: 设为True时,程序将在发生异常时暂停,以便调试
        :return: 以装饰器的方式应用于测试函数
        """
        def exception_record_wrapper(test_func):
            @wraps(test_func)  # wraps用于保留函数的元信息
            def test_func_wrapper(*test_func_args, **test_func_kwargs):
                return ExceptionRecord(pause).call(test_func, *test_func_args, **test_func_kwargs)
    
            return test_func_wrapper
    
        return exception_record_wrapper
    
    
    class ExceptionRecord:
        def __init__(self, pause):
            self.driver = None
            self.sleep_time = 10000 if pause else None
    
        def call(self, test_func, *test_func_args, **test_func_kwargs):
            self.driver = self.get_driver(test_func_args)
            try:
                test_func(*test_func_args, **test_func_kwargs)
            except:
                self.save_exception_related_information()
                if self.sleep_time:
                    print(traceback.format_exc())
                    time.sleep(self.sleep_time)
                raise
    
        def save_exception_related_information(self):
            current_date = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d")
            current_time = datetime.datetime.strftime(datetime.datetime.now(), "%H_%M_%S")
            dir_path = f'{EXCEPTION_RECORD_DIR_PATH}\{current_date}\{current_time}'
            if not os.path.isdir(dir_path):
                os.makedirs(dir_path)
            self.driver.get_screenshot_as_file(f'{dir_path}\screenshort.png')
            self.save_browser_console_data(dir_path)
    
        def save_browser_console_data(self, dir_path):
            for log_type in self.driver.log_types:
                log_data = pprint.pformat(self.driver.get_log(log_type))
                with open(f'{dir_path}\{log_type}_log.txt', 'w') as file_pipeline:
                    file_pipeline.write(log_data)
    
        @staticmethod
        def get_driver(test_func_args):
            # 参数检查,分别判断参数个数,参数名,参数类型是否正确
            if len(test_func_args) > 0 and DRIVER_ATTRIBUTE_NAME in dir(test_func_args[0]):
                driver = test_func_args[0].driver
                if isinstance(driver, WebDriver):
                    return driver
                else:
                    raise ValueError("测试类的driver属性不是浏览器驱动对象")
            else:
                raise ValueError("无法获得测试类的driver属性")
    
    
    class _TestClassExample(TestCase):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # 注意:浏览器驱动必须作为类属性,且命名为driver
            chrome_driver = ChromeDriver(headless=False, disable_w3c=True)
            self.driver = chrome_driver.driver
    
        @record_exception_related_info()
        def test_method_example(self):
            self.driver.get("http://www.baidu.com")
            self.driver.get("raise_exception")
    
  • 相关阅读:
    Vue之数据排序加签
    微信小程序之评分页面
    Vue之展示PDF格式的文档
    动态规划问题思考(DP)
    LitJson的使用
    c#事件管理器
    unity shader 学习
    unity ugui图片自适应文字内容大小
    unity3d各种OpenFileDialog操作
    ue4 使用3dsmax制作布料的插件及下载位置
  • 原文地址:https://www.cnblogs.com/lokvahkoor/p/11934865.html
Copyright © 2011-2022 走看看