• [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")
    
  • 相关阅读:
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    Java中时间与时间戳的转换
    python爬取网页数据
    selenium爬取网页内容知识点总结(代码均亲测可用)
    【LeetCode 5】 最长回文子串
    【LeetCode 4】寻找两个有序数组的中位数
    【LeetCode 3】无重复字符的最长子串
    【LeetCode 1】两数之和
    【LeetCode 2】两数相加
    【3-4】数字三角形问题
  • 原文地址:https://www.cnblogs.com/lokvahkoor/p/11934865.html
Copyright © 2020-2023  润新知