解决python自动化操作异常处理的问题

在python自动化领域,往往要用到pyautogui,pywin32等模块实现自动化操作。然而,这种自动化操作,本身具有一定的局限性,其中最主要的一个问题就是,一旦执行结果不按照脚本预设的来执行,往往会抛出异常,导致程序中断。

解决这个问题,主要有这么几种思路:

第一,每一次操作后分情况讨论。这种方法的弊端是代码过于冗长,不够直观。

第二,对异常进行处理,例如重启函数。但是这里遇到一个问题,重启次数是多少,怎么避免循环,如何根据异常类型实时修改重启函数的参数,对异常的后处理操作后如何再次重启回归正轨等等。要解决这些问题,代码逻辑复杂。

基于这个原因,本文实现通过装饰器,实现了对函数的封装。主要有以下几个功能:

1、指定重启函数的次数。

2、限定重启函数的重启时间。

3、可以指定异常处理函数,在抛出异常后,执行处理函数,然后再次尝试重启。

4、可以根据函数重启的次数,传入不同的参数值。

其代码如下:

(1)修饰器部分:

def retryOnException(maxAttempts=3, delay=1, exceptions=(Exception,), timeout=None, onFail=None, paramModifier=incrementParam):
    def decorator(func):
        def wrapper(*args, **kwargs):
            startTime = time.time()
            attempts = 0
            while attempts < maxAttempts:
                if paramModifier:
                    new_args, new_kwargs, args, kwargs = paramModifier(*args, **kwargs)
                try:
                    return func(*new_args, **new_kwargs)
                except exceptions as e:
                    print("An exception occured:{}".format(e))
                    print("Attempting to retry... Attempt {}/{}".format(attempts+1, maxAttempts))
                    time.sleep(delay)
                    attempts += 1
                    if timeout and time.time() - startTime > timeout:
                        if onFail:
                            result =  onFail(*args, **kwargs)
                            if result is not None: #表明问题已经修复了
                                attempts = 0 #重置尝试次数
                                continue
                            else:
                                #表明问题没有修复,执行没有结果
                                raise RuntimeError(
                                    "Function {} failed after {} onFail.".format(func.__name__, maxAttempts))
                        else:
                            raise TimeoutError("Function {} time out after {} seconds.".format(func.__name__, timeout))
            if onFail:
                result = onFail(*args, **kwargs)
                if result is not None:  # 表明问题已经修复了
                    return wrapper(*args, **kwargs)
                else:
                    # 表明问题没有修复,执行没有结果
                    raise RuntimeError(
                        "Function {} failed after {} onFail.".format(func.__name__, maxAttempts))
            else:
                raise RuntimeError("Function {} failed after {} attempts.".format(func.__name__, maxAttempts))
        return wrapper
    return decorator

(2)参数选择器

def incrementParam(*args, **kwargs):
    if "increment" in kwargs:
        index = kwargs["increment"]
        kwargs["increment"] += 1
        new_args, new_kwargs = kwargs["argsList"][index] #{"increment":0, "argsList":[([],{}),]}
        return new_args, new_kwargs, args, kwargs
    else:
        return args, kwargs, args, kwargs

(3)异常处理函数和主程序代码

def hello(*args, **kwargs):
    print("处理异常情况部分")
    return None

@retryOnException(maxAttempts=3, delay=2, timeout=10, onFail=hello)
def testFunction(a, b, c, good):
    print("trying to excute function...")
    print(a, b, c, good)
    import random
    if random.randint(0, 0) == 0:
        raise ValueError("someting went wrong!")
    return "Function executed successfully"

try:
    print(testFunction(increment = 0, argsList = [([1,2,3,4], {}), ([2,2,2,1],{}), ([3,4,3], {"good":3})]))
except(RuntimeError, TimeoutError) as e:
    print("================")
    print(str(e))

try:
    print( testFunction(1, 2, "yes", good="yes") )
except Exception as e:
    print("huhuu")
pass

以上代码非常简洁,可以完美实现对函数异常的重启处理,并且具有一定的异常修复功能。例如:在微信自动化程序项目中,由于交互问题导致的偶发性发送信息或者文件失败,可以通过该方法实现异常判别并自动处理,具有比较好的代码稳定性。

  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值