首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >巨蟒中的RecursionError

巨蟒中的RecursionError
EN

Stack Overflow用户
提问于 2018-12-14 19:54:41
回答 1查看 11.1K关注 0票数 4

我是蟒蛇的新手,机械工程专业毕业。所以我对计算机科学没有太多的理论知识。我正试图开发一个基本的机器人或漫游者,无论怎样,我总是想要检查来自Arduino的数据。起初,Python程序运行得很好,但是过了一段时间,程序失败了。

我在谷歌搜索了"RecursionError:最大递归深度.“对我来说,任何答案都是不够的(sys.setrecursionlimit(10000),尾部递归函数,分离器)。

第一个问题:

代码语言:javascript
复制
def oku():
    print("qwerty")
    oku()

oku()

当执行这些代码时,程序失败了。

RecursionError:在选择对象时超过了最大递归深度。

代码语言:javascript
复制
def oku():
    print("qwerty")

while True:
    oku()

当我执行这段代码时,没有问题。为什么?

第二个问题:

代码语言:javascript
复制
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()

程序运行一段时间后会出现此错误。

代码语言:javascript
复制
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)时:

代码语言:javascript
复制
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)

我没有遇到任何错误。这个解决方案正确吗?程序是否产生一个前瞻性错误与时间的解决方案?

这里通信类代码..。

代码语言:javascript
复制
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"
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-14 20:03:24

第一个问题

Python具有最大递归深度,以防止堆栈溢出。这意味着调用堆栈不能超过最大深度(默认为1000)。因此,在第一个示例中,函数oku多次调用自己,每次都向调用堆栈添加一个调用。一旦oku调用自己1000次,就会达到最大递归深度,并引发一个RecursionError

在第二个示例中,oku可能被调用超过1000次,但每次调用都是在上一次调用完成执行之后进行的。因此,一个调用被添加到调用堆栈中,然后删除,然后再添加另一个调用,然后再删除,等等。在第一个示例中,由于对oku的下一次调用发生在当前的oku调用中,因此调用堆栈中没有任何调用被删除。

第二个问题

这里的问题和你的第二个版本起作用的原因似乎与第一个问题中的例子大致相同。基本问题是,在没有任何停止条件的情况下,递归调用相同的函数。但是,在这种情况下,您可以通过timer_read.run()而不是直接进行递归调用。

我认为获得Fatal Python error: Cannot recover from stack overflow的原因是,由于递归是通过线程计时器发生的,所以Python没有将此示例识别为递归。因此,Python不知道引发RecursionError,堆栈就会溢出。

Solution/Notes

在这些例子中,似乎根本不需要使用递归,也没有使用递归的好处。这里使用递归代替循环,循环将是一个更好的解决方案。特别是因为你似乎想要这个过程无限期地重复。

在使用递归时,需要确保有基本情况或停止条件。本质上,这是当您的过程被“完成”时(无论这对应用程序意味着什么)。这将有助于防止堆栈溢出(但不是保证)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53786145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档