最新消息:20210917 已从crifan.com换到crifan.org

【已解决】优化函数多次尝试某函数直到成功的逻辑:增加返回值为多个tuple的支持和返回全部信息

返回 crifan 329浏览 0评论
折腾:
【未解决】安卓游戏暗黑觉醒自动化:进入首页后就是首充充值弹框
期间,对于之前函数:
utils/common_utils.py
    def multipleRetry(functionInfoDict, maxRetryNum=5, sleepInterval=0.1, isShowErrWhenFail=True):
        """
        do something, retry mutiple time if fail


        Args:
            functionInfoDict (dict): function info dict contain functionCallback and [optional] functionParaDict
            maxRetryNum (int): max retry number
            sleepInterval (float): sleep time of each interval when fail
            isShowErrWhenFail (bool): show error when fail if true
        Returns:
            bool
        Raises:
        """
        doSuccess = False
        functionCallback = functionInfoDict["functionCallback"]
        functionParaDict = functionInfoDict.get("functionParaDict", None)


        curRetryNum = maxRetryNum
        while curRetryNum > 0:
            if functionParaDict:
                doSuccess = functionCallback(**functionParaDict)
            else:
                doSuccess = functionCallback()
            
            if doSuccess:
                break
            
            time.sleep(sleepInterval)
            curRetryNum -= 1


        if not doSuccess:
            if isShowErrWhenFail:
                functionName = str(functionCallback)
                # '<bound method DevicesMethods.switchToAppStoreSearchTab of <src.AppCrawler.AppCrawler object at 0x1053abe80>>'
                logging.error("Still fail after %d retry for %s", maxRetryNum, functionName)
        return doSuccess
具体调用举例:
isGotoPay = CommonUtils.multipleRetry({"functionCallback": self.isGotoPayPopupPage})
有个缺点:
传入的函数,返回值必须是:单个的bool变量
而不支持:返回多个值的情况
希望:增加支持传入函数返回值是tuple或别的类型的变量的情况
    至少此处是tuple,三个值,则第一个值要是bool
如果支持了这种返回多个值的tuple类型,最好还要:增加把完整的返回值返回给调用者
            if functionParaDict:
                # doSuccess = functionCallback(**functionParaDict)
                respValue = functionCallback(**functionParaDict)
            else:
                # doSuccess = functionCallback()
                respValue = functionCallback()
            
            doSuccess = False
            if isinstance(respValue, bool):
                doSuccess = bool(respValue)
            elif isinstance(respValue, tuple):
                doSuccess = respValue first value
期间又遇到:对于tuple,不知道具体几个值,希望获取第一个值
如何写?
python get first element of tuple
How to get the first element of each tuple in a list in Python
Get the first element of each tuple in a list in Python – Stack Overflow
好像就是支持 someTuple[0] 即可获取第一个值?
python – Getting one value from a tuple – Stack Overflow
Tuples can be indexed just like lists.
就是的,可以像list一样去索引tuple
就像代码:
        finalReturnValue = None


            doSuccess = False
            if isinstance(respValue, bool):
                doSuccess = bool(respValue)
            elif isinstance(respValue, tuple):
                doSuccess = bool(respValue[0])
            elif isinstance(respValue, list):
                doSuccess = bool(respValue[0])
            else:
                Exception("multipleRetry: Not support type of return value: %s" % respValue)

            if doSuccess:
                if isRespFullRetValue:
                    finalReturnValue = respValue
                else:
                    finalReturnValue = doSuccess
                break
去调试看看
调用:
    def isGotoPayPopupPage_multipleRetry(self, isRespFullInfo=False):
        """鉴于 暗黑觉醒 的 首充弹框 的检测很不稳定,所以 增加此函数 多次尝试 以确保 当是首充页面时,的确能稳定的检测出的确是"""
        respBoolOrTuple = CommonUtils.multipleRetry(
            {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": isRespFullInfo,
                },
                "isRespFullRetValue": isRespFullInfo,
            }
        )
        return respBoolOrTuple
然后根据此处的isRespFullInfo决定是:
返回单个bool,还会返回完整信息tuple(带坐标位置信息)
其调用:
isGotoPay = self.isGotoPayPopupPage_multipleRetry()
发现参数错误,调整为:
    def isGotoPayPopupPage_multipleRetry(self, isRespLocation=False):
        """鉴于 暗黑觉醒 的 首充弹框 的检测很不稳定,所以 增加此函数 多次尝试 以确保 当是首充页面时,的确能稳定的检测出的确是"""
        respBoolOrTuple = CommonUtils.multipleRetry(
            {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": isRespLocation,
                },
                "isRespFullRetValue": isRespLocation,
            }
        )
        return respBoolOrTuple


        isGotoPay, matchResult, imgPath = self.isGotoPayPopupPage_multipleRetry(isRespLocation=True)
去调试看看
终于调试到:传入True的情况了
结果调用写错了,改为:
        respBoolOrTuple = CommonUtils.multipleRetry(
            functionInfoDict = {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": isRespLocation,
                },
            },
            isRespFullRetValue = isRespLocation,
        )
再去调试
也支持返回多个值的tuple类型了:
不过返回值要改:
        # return doSuccess
        return finalReturnValue
即可。
【总结】
此处最终代码:
    def multipleRetry(functionInfoDict, maxRetryNum=5, sleepInterval=0.1, isShowErrWhenFail=True, isRespFullRetValue=False):
        """do something, retry if single call failed, retry mutiple time until max retry number


        Args:
            functionInfoDict (dict): function info dict contain functionCallback and [optional] functionParaDict
            maxRetryNum (int): max retry number
            sleepInterval (float): sleep time (seconds) of each interval when fail
            isShowErrWhenFail (bool): show error when fail if true
            isRespFullRetValue (bool): whether return full return value of function call
        Returns:
            isRespFullRetValue=False: bool
            isRespFullRetValue=True: bool / tuple/list/...
        Raises:
        """
        finalReturnValue = None
        doSuccess = False
        functionCallback = functionInfoDict["functionCallback"]
        functionParaDict = functionInfoDict.get("functionParaDict", None)


        curRetryNum = maxRetryNum
        while curRetryNum > 0:
            if functionParaDict:
                # doSuccess = functionCallback(**functionParaDict)
                respValue = functionCallback(**functionParaDict)
            else:
                # doSuccess = functionCallback()
                respValue = functionCallback()
            
            doSuccess = False
            if isinstance(respValue, bool):
                doSuccess = bool(respValue)
            elif isinstance(respValue, tuple):
                doSuccess = bool(respValue[0])
            elif isinstance(respValue, list):
                doSuccess = bool(respValue[0])
            else:
                Exception("multipleRetry: Not support type of return value: %s" % respValue)


            if doSuccess:
                if isRespFullRetValue:
                    finalReturnValue = respValue
                else:
                    finalReturnValue = doSuccess
                break


            time.sleep(sleepInterval)
            curRetryNum -= 1


        if not doSuccess:
            if isShowErrWhenFail:
                functionName = str(functionCallback)
                # '<bound method DevicesMethods.switchToAppStoreSearchTab of <src.AppCrawler.AppCrawler object at 0x1053abe80>>'
                logging.error("Still fail after %d retry for %s", maxRetryNum, functionName)
        # return doSuccess
        return finalReturnValue
调用:
    def isGotoPayPopupPage_multipleRetry(self, isRespLocation=False):
        """鉴于 暗黑觉醒 的 首充弹框 的检测很不稳定,所以 增加此函数 多次尝试 以确保 当是首充页面时,的确能稳定的检测出的确是"""
        respBoolOrTuple = CommonUtils.multipleRetry(
            functionInfoDict = {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": isRespLocation,
                },
            },
            isRespFullRetValue = isRespLocation,
        )
        return respBoolOrTuple
其中此处的:isRespLocation可能是True,即:
        respBoolOrTuple = CommonUtils.multipleRetry(
            functionInfoDict = {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": True,
                },
            },
            isRespFullRetValue = True,
        )
或False:
        respBoolOrTuple = CommonUtils.multipleRetry(
            functionInfoDict = {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": False,
                },
            },
            isRespFullRetValue = False,
        )
=
        respBoolOrTuple = CommonUtils.multipleRetry(
            functionInfoDict = {
                "functionCallback": self.isGotoPayPopupPage,
                "functionParaDict": {
                    "isRespLocation": False,
                },
            },

转载请注明:在路上 » 【已解决】优化函数多次尝试某函数直到成功的逻辑:增加返回值为多个tuple的支持和返回全部信息

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.192 seconds, using 23.26MB memory