0

I keep getting this error"RuntimeError: maximum recursion depth exceeded while calling a Python object" when I try running my host program for smart card test tool with 600 tests and I get this error after the 300th test, I tried "sys.setrecursionlimit(10000)" and that fixed the problem, but I do know that this is not the best way to go about this error, how can I change my code so I don't run into this error:

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("")
5
  • 1
    self.SndRcv calls self.processResponse, and self.processResponse calls self.SndRcv. Can you see why that can lead to arbitrary depth recursion? Commented Nov 4, 2016 at 14:44
  • To understand recursion you first need to understand recursion ... Commented Nov 4, 2016 at 14:45
  • 1
    Expanding a bit:, SndRcv never returns and processResponse only returns if ciMsgType is None. Commented Nov 4, 2016 at 14:55
  • You might be able to implement them as generators/coroutines - you'll have to learn a bit - this reminds me of a trampoline. Commented Nov 4, 2016 at 15:02
  • @PM2Ring yes I can see that, I am new to python programming and not sure how to refactor this in order to make it work like it does right now (except the error), Commented Nov 4, 2016 at 16:32

1 Answer 1

0

You used recursion to code an inherently iterative process. You're not actually reducing a large problem to a smaller one; you're stepping through a sequence of inputs. Once you process an input and report the response, you're done with it. There's no reason to keep it's context on the call stack. When you hit the final test and return through your thousand-plus calls, you do nothing with the results or function state to return to the main program.

Rewrite this as a straightforward iteration. How do you start? How do you progress from one test to another? How do you know when you're done? For instance, it's quite possible that your outermost loop will hinge on a simple while:

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

Does that get you moving?

Sign up to request clarification or add additional context in comments.

2 Comments

the way I start it is calling the start session, which I did not include in the code here. Basically I send the command to start session using SndRcv to the test tool and depending on the type of the response I get back from resp = device_api.receive() I pass that to processResponse(resp) in order to analyze what next step I should send and receive and I pass the received message to the processResponse every time, and I believe this is what is causing the error, so I need to refractor this somehow so that I don't keep calling the processResponse(resp)...
Fine. The basic principle is still the same: The upper loop moves from one test to the next. You may have a subroutine analyze the response, but pass that information back to the upper loop for the next iteration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.