简体   繁体   中英

RecursionError in python

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"

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM