5

I am new in python and I graduated in mechanical engineering. So I have no a lot of theoretical knowledge of computer science. I'm trying to develope a basic robot or rover whatever and I constantly want to check incoming datas from Arduino. At first, Python program worked very nicely but after a while the program failed.

I searched in google about "RecursionError: maximum recursion depth..." and any answer was not enough for me (sys.setrecursionlimit(10000), tail recursion function, detactors).

First question:

def oku():
    print("qwerty")
    oku()

oku()

when This codes was executed, the program is failing.

RecursionError: maximum recursion depth exceeded while pickling an object.

def oku():
    print("qwerty")

while True:
    oku()

There is no problem when I execute this code. Why?

Second question:

from Arnocom import communication as COM
from threading import Timer
from Coordinates import location

class MainGUI(components):

def __init__(self, window):

    super().__init__(window)
    self.btn_ext.config(command=self.exit)
    self.btn_f.config(command=motions.foward)
    self.btn_s.config(command=motions.stop)
    # self.timer_flag = True

    lst = COM.main()
    for i in range(len(lst)):
        self.show_info(lst[i])


def show_info(self, info):
    self.lstbx_glnveri.insert(END, info)
    self.lstbx_glnveri.see(END)

def call_read(self):
        try:
            gln_veri = COM.read()
            print(gln_veri)
            if gln_veri is None:
                pass
            else:
                ow = location.analysis_data(gln_veri)
                self.show_info(ow)
        except Exception:
            pass
        timer_read.run()


root = Tk()

my_gui = MainGUI(root)

timer_read = Timer(0.01, my_gui.call_read)
timer_read.start()

root.mainloop()

The program gives this error after running for a while.

Fatal Python error: Cannot recover from stack overflow.

Current thread 0x000005c0 (most recent call first):
  File "C:\Users\evil\Desktop\_Project_GUI\venv\lib\site- 
  packages\serial\serialwin32.py", line 272 in read
  File "C:\Users\evil\Desktop\_Project_GUI\venv\lib\site- 
  packages\serial\serialutil.py", line 659 in read_until
  File "C:\Users\evil\Desktop\_Project_GUI\Arnocom.py", line 40 in read
  File "C:/Users/evil/Desktop/_Project_GUI/Form.py", line 38 in call_read
  File "C:\Users\evil\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 1158 in run
  File "C:/Users/evil/Desktop/_Project_GUI/Form.py", line 51 in call_read
 .
 same errors
 .
  File "C:\Users\evil\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 1158 in run
  File "C:/Users/evil/Desktop/_Project_GUI/Form.py", line 51 in call_read
 ...

Thread 0x00001648 (most recent call first):
  File "C:\Users\evil\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1283 in mainloop
  File "C:/Users/evil/Desktop/_Project_GUI/Form.py", line 77 in <module>

but when I changed call_read(self) like this:

self.timer_flag = True

def call_read(self):
    while self.timer_flag:
        try:
            gln_veri = COM.read()
            print(gln_veri)
            if gln_veri is None:
                pass
            else:
                ow = location.analysis_data(gln_veri)
                self.show_info(ow)
        except Exception:
            pass
        time.sleep(0.1)

I dont encounter any error. Is this solution correct? Does the program generate a forward-looking error with while solution?

here communicaiton class code..

import serial
import serial.tools.list_ports as port_list

class communication:

  @classmethod
  def main(cls):

    # store error message
    cls.msj_gndr = []
    cls.Arduino = serial.Serial()
    cls.Arduino.baudrate = 115200
    cls.Arduino.timeout = 0.01
    # collect error message
    cls.msj_gndr.append(cls.port_list())
    cls.msj_gndr.append(cls.open_port())
    cls.msj_gndr.append(cls.check_connection())
    return cls.msj_gndr

  @classmethod
  def read(cls):
    try:
        gelenveri = cls.Arduino.read_until(b';')
        if gelenveri != b'':
            return gelenveri
    except Exception:
        return "Connection Error"
4
  • Try reading How to Ask Commented Dec 14, 2018 at 19:56
  • 1
    For the first one you are just looping throught infinity with while True Commented Dec 14, 2018 at 19:57
  • 1
    I liked your first question a lot. The two oku() functions are fundamentally different, the concept is called recursion vs iteration another link and, fittingly enough, unchecked recursion leads to a recursion error due to, well... stack overflow. And so, welcome to stack overflow! Your second question is frankly too long to inspect, you may want to narrow it down to relevant parts. But i suspect it is related to recursion vs iteration. Commented Dec 14, 2018 at 20:00
  • 1
    StackOverflow's Q&A style works best if you limit each post to one question. There's nothing stopping you from making several separate posts each with a different question, though. Commented Dec 14, 2018 at 20:05

1 Answer 1

7

First Question

Python has a maximum recursion depth in order to prevent a stack overflow. This means that the call stack cannot exceed the maximum depth (1000 by default). So in your first example, the function oku calls itself many times, each time adding a call to the call stack. Once oku calls itself 1000 times the maximum recursion depth is hit and Python raises a RecursionError.

In your second example, oku may be called more than 1000 times, but each call is made after the previous call has completed execution. So one call is added to the call stack, then removed, then another is added, and removed again, and so on. In the first example, since the next call to oku happens inside the current call of oku, no calls are removed from the call stack.

Second Question

The problem here and reason your second version works seem to be roughly the same as in your examples from the first question. The basic problem is that you call the same function recursively without any stopping conditions. In this case, however you make the recursive call through timer_read.run() rather than directly.

I believe the reason you get Fatal Python error: Cannot recover from stack overflow is because Python does not recognize this example as recursion since the recursion is happening through the threading Timer. Thus Python doesn't know to raise a RecursionError and the stack overflows.

Solution/Notes

It seems in these examples that there is no need use or benefit from using recursion at all. Recursion here is being used instead of a loop and a loop would be a better solution. Especially since it seems like you want the process to repeat indefinitely.

When using recursion you need to make sure that you have a base case or stopping condition. Essentially this is when your process is "done" (whatever that may mean for the application). This will help prevent stack overflows (not a guarantee though).

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

1 Comment

Thanks for answers. you've explained my questions very clearly.

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.