【问题标题】:runtimeerror: maximum recursion depth exceeded pythonruntimeerror:超出最大递归深度python
【发布时间】:2017-03-18 10:44:36
【问题描述】:

当我尝试运行具有 600 次测试的智能卡测试工具的主机程序并且在第 300 次测试后出现此错误时,我不断收到此错误“RuntimeError:调用 Python 对象时超出最大递归深度”,我尝试了“sys .setrecursionlimit(10000)" 并解决了问题,但我知道这不是解决此错误的最佳方法,如何更改我的代码以免遇到此错误:

def SndRcv(self,request):
    print ">> ", request
    device_api.send(request)
    resp = device_api.receive()
    print "<< ", resp
    self.processResponse(resp)

def processResponse(self, K400Message):
    global mWaitingCardRemoval
    ciMsg = card_interface_response
    ciMsgType = card_interface_response.ci_msg

    if ciMsgType is None:
        print 'weird, malformed protobuf response'
        return
    whichMsg = ciMsgType.WhichOneof('msg')
    print 'msg = ' + str(whichMsg)
    if whichMsg is 'collision':
        self.StartSession()
    elif whichMsg is 'card_removed':
        if ciMsgType.issuer== ci.CARD_INTERFACE_MASK_CxLESS:                
            mWaitingCardRemoval &= ~(ciMsgType.issuer)
            if EndofSession is False:
                self.parseMessage()
            if mWaitingCardRemoval !=0:
                self.parseMessage()
            self.StartSession()
    elif whichMsg is 'waiting_removal':
        if EndofSession is False:
            self.parseMessage()
        else:
            mWaitingCardRemoval |= ciMsgType.issuer
    elif whichMsg is 'card_detected':
        mode = ciMsgType.issuer
        reqMsg = pm.get_Deactivate((ci.CARD_INTERFACE_MASK_ANY)& ~(ciMsgType.issuer))
        self.SendOnly(reqMsg)
        acceptMsg = pm.get_Activate(mode)
        self.SndRcv(acceptMsg)
    elif whichMsg is 'card_ready':
        self.StartLoop(ciMsgType.issuer)
    elif whichMsg is 'rapdu':
        self.processCardAPDUResponse(ciMsgType.issuer, ciMsg.data.encode('hex'))
    elif whichMsg is 'card_not_responding':
        if ciMsgType.issuer == ci.CARD_INTERFACE_MASK_CONTACT:
            self.EndCardSession(ciMsgType.issuer,True)
        else:
            self.EndCardSession(ciMsgType.issuer, False)
    elif whichMsg is 'resp_special':
        if ciMsg.data.encode('hex') > 0:
            logging.info(ciMsg.data.encode('hex'))
        else:
            logging.info("")

【问题讨论】:

  • self.SndRcv 调用self.processResponseself.processResponse 调用self.SndRcv。你能明白为什么这会导致任意深度递归吗?
  • 要了解递归,您首先需要了解递归...
  • 扩展一点:SndRcv 永远不会返回,processResponse 只会返回 if ciMsgType is None
  • 您也许可以将它们实现为生成器/协程 - you'll have to learn a bit - 这让我想起了 a trampoline
  • @PM2Ring 是的,我可以看到,我是 python 编程的新手,不知道如何重构它以使其像现在一样工作(除了错误),

标签: python recursion


【解决方案1】:

您使用递归来编写一个固有的迭代过程。您实际上并没有将一个大问题简化为一个较小的问题。您正在逐步完成一系列输入。处理输入并报告响应后,您就完成了。没有理由将其上下文保留在调用堆栈上。当您完成最终测试并通过数千次调用返回时,您对结果或函数状态不做任何操作以返回主程序。

将其重写为简单的迭代。你如何开始?您如何从一项测试进展到另一项测试?你怎么知道你什么时候完成?例如,您的最外层循环很有可能取决于一个简单的 while

# Get first response
while ciMsgType is not None:
    # Process this response
    # Get next response

这会让你感动吗?

【讨论】:

  • 我启动它的方式是调用启动会话,这里的代码中没有包含它。基本上,我将使用 SndRcv 启动会话的命令发送到测试工具,并根据我从 resp = device_api.receive() 返回的响应类型将其传递给 processResponse(resp) 以分析下一步我应该做什么发送和接收,我每次都将接收到的消息传递给 processResponse,我相信这是导致错误的原因,所以我需要以某种方式折射这个,这样我就不会继续调用 processResponse(resp)...
  • 很好。基本原理还是一样的:上层循环从一个测试移动到下一个测试。您可能有一个子例程分析响应,但将该信息传递回上层循环以进行下一次迭代。
猜你喜欢
  • 2015-04-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
相关资源
最近更新 更多