簡體   English   中英

python中的RecursionError

[英]RecursionError in python

我是python的新手,我畢業於機械工程專業。 因此,我對計算機科學沒有太多的理論知識。 我正在嘗試開發基本的機器人或漫游者,而我一直想檢查來自Arduino的傳入數據。 剛開始,Python程序運行得很好,但是一段時間后程序失敗了。

我在Google中搜索了“ RecursionError:最大遞歸深度...”,對我來說,任何答案都還不夠(sys.setrecursionlimit(10000),尾遞歸函數,檢測器)。

第一個問題:

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

oku()

當執行此代碼時,程序失敗。

RecursionError:腌制對象時超出了最大遞歸深度。

def oku():
    print("qwerty")

while True:
    oku()

當我執行此代碼時沒有問題。 為什么?

第二個問題:

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

程序運行一段時間后給出此錯誤。

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>

但是當我像這樣更改call_read(self)時:

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)

我沒有遇到任何錯誤。 這個解決方案正確嗎? 程序在使用while解決方案時是否會產生前瞻性錯誤?

這里是通訊類代碼。

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"

第一個問題

Python具有最大的遞歸深度,以防止堆棧溢出。 這意味着調用堆棧不能超過最大深度(默認為1000)。 因此,在第一個示例中,函數oku會多次調用自身,每次將調用添加到調用堆棧中。 一旦oku調用自身1000倍的最大遞歸深度,Python就會引發RecursionError

在第二個示例中, oku可能被調用1000次以上,但是每個調用都是在上一個調用完成執行之后進行的。 因此,將一個調用添加到調用堆棧中,然后刪除,然后再添加另一個,然后再次刪除,依此類推。 在第一個例子,因為下一個呼叫oku的當前呼叫內發生的oku ,沒有調用從調用堆棧中刪除。

第二個問題

這里的問題和您的第二個版本工作的原因似乎與第一個問題中的示例大致相同。 基本問題是,您在沒有任何停止條件的情況下遞歸調用同一函數。 但是,在這種情況下,您是通過timer_read.run()而不是直接進行遞歸調用的。

我相信您會收到Fatal Python error: Cannot recover from stack overflow的原因是,因為遞歸是通過線程計時器進行的,所以Python無法將此示例識別為遞歸。 因此,Python不知道引發RecursionError並且堆棧溢出。

解決方案/注意事項

在這些示例中,似乎完全沒有必要使用遞歸或從中受益。 這里使用遞歸而不是循環,而循環將是更好的解決方案。 特別是因為您似乎希望該過程無限期地重復。

使用遞歸時,需要確保您具有基本情況或停止條件。 從本質上講,這是您的流程“完成”的時間(無論對應用程序意味着什么)。 這將有助於防止堆棧溢出(盡管不能保證)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM