【问题标题】:Is there a way around RecursionError: maximum recursion depth exceeded while calling a Python object?有没有办法解决 RecursionError:调用 Python 对象时超出最大递归深度?
【发布时间】:2020-01-25 15:07:05
【问题描述】:

我正在制作一个调用自身的函数,但出现错误:RecursionError:调用 Python 对象时超出了最大递归深度,有没有办法解决这个问题。更具体地说,我在第 35 行得到它,好的,frame = cap.read() 由于程序中的 .after 功能,我无法放置 while 循环。

import cv2
from tkinter import *
import PIL
from PIL import Image, ImageTk

root = Tk()
root.bind('<Escape>', lambda e: root.quit())
lmain = Label(root)
lmain.pack()

print("[INFO] Making variables")
ImageSource = 0
window_name = "AutoCam"
width = 600
height = 800
cap = cv2.VideoCapture(ImageSource)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
print("[INFO] Made variables ")


def ShowFrame(frame):
    print("[INFO] making image.")
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = PIL.Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    lmain.imgtk = imgtk
    lmain.configure(image=imgtk)
    print("[INFO] After 10 initializing")
    lmain.after(10, CheckSource)
    print("[INFO] Showed image")


def CheckSource():
    ok, frame = cap.read()

    if ok:
        print("[INFO] Ok is triggered")

        if cv2.waitKey(1) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            cv2.waitKey(0)
            print("[INFO] Exiting app after command")

        ShowFrame(frame)

    else:

        lmain.after(10, CheckSource())


CheckSource()
root.mainloop()

我们将不胜感激任何和所有的帮助。 有人还可以解释如何避免这种情况以备将来使用吗?

[编辑]

the error message is:
  Traceback (most recent call last):
   File "C:/Users/Gotta/Documents/AutoCamPy.py", line 52, in <module>
   CheckSource()
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
 [Previous line repeated 995 more times]
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 35, in CheckSource
  ok, frame = cap.read()
RecursionError: maximum recursion depth exceeded while calling a Python 
object

【问题讨论】:

  • 运行您的代码时不会出现任何错误。
  • 什么?我得到一个 RecursionError:调用 Python 对象时超出了最大递归深度
  • 你必须在没有插入相机的情况下运行它...
  • 因为应用程序假设连接后会自动显示摄像头供稿
  • 你有多余的括号:.after(..., CheckSource()) - 更改为.after(..., CheckSource)

标签: python opencv recursion tkinter


【解决方案1】:

通过堆栈跟踪,您可以确定递归发生在第 49 行(这是被执行多次的行)

File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
File "C:/Users/Gotta/Documents/AutoCamPy.py", line 49, in CheckSource
  lmain.after(10, CheckSource())
 [Previous line repeated 995 more times]

它达到递归限制的原因是因为.after 函数(https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.after-method) 需要一个回调函数作为第二个参数,但是你传递了调用@987654324 的结果 @ 反而。您应该传递 CheckSource 而不是 CheckSource() 作为第二个参数:

lmain.after(10, CheckSource)

【讨论】:

    【解决方案2】:

    要以简单的方式处理此问题,您可以编写 try/except 语句来捕获此错误。在您确切知道错误是什么之前,您可以使用全部捕获,但我建议您在知道具体错误后处理具体错误。

    也就是说,我在您的代码中更改了一些内容以对其进行一些清理并更严格地遵循 PEP8 标准。

    你真的应该使用import tkinter as tk 而不是使用*。这将有助于防止覆盖已导入的方法。

    接下来你的 lambda 已经结束了,只需执行 root.quit 即可。我们想保存对命令的引用而不是执行它,我们通过删除括号来做到这一点。您的第二个 after 语句也存在同样的问题。

    最后你导入PIL,然后专门从 PIL 导入。您不需要两者都做。如果您只需要ImageImageTk,那么只需执行from PIL import Image, ImageTk,如果您需要PIL 提供的很多东西,那么您可以简单地执行import PIL 并从那里使用PIL. 前缀。

    这是您使用 try/except 语句清理后的代码。如果您有任何问题,请告诉我。

    import tkinter as tk
    from PIL import Image, ImageTk
    import cv2
    
    
    root = tk.Tk()
    root.bind('<Escape>', root.quit)
    lmain = tk.Label(root)
    lmain.pack()
    ImageSource = 0
    window_name = "AutoCam"
    width = 600
    height = 800
    cap = cv2.VideoCapture(ImageSource)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
    
    
    def show_frame(frame):
        cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
        img = Image.fromarray(cv2image)
        imgtk = ImageTk.PhotoImage(image=img)
        lmain.imgtk = imgtk
        lmain.configure(image=imgtk)
        lmain.after(10, check_source)
    
    
    def check_source():
        try:
            ok, frame = cap.read()
            if ok:
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    cv2.destroyAllWindows()
                    cv2.waitKey(0)
                show_frame(frame)
            else:
                lmain.after(10, check_source)
        except:
            print('Connection failed for some reason!')
    
    
    check_source()
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-07
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 2020-01-05
      • 1970-01-01
      相关资源
      最近更新 更多