Есть ли способ обойти RecursionError: максимальная глубина рекурсии превышена при вызове объекта Python? - PullRequest
0 голосов
/ 25 сентября 2019

Я делаю функцию, которая вызывает себя, но я получаю ошибку: RecursionError: превышена максимальная глубина рекурсии при вызове объекта Python. Есть ли способ обойти это?Более конкретно, я получаю его для строки 35, хорошо, frame = cap.read () Я не могу поставить цикл while из-за функции .after в моей программе.

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

Любая и вся помощь будеточень ценитсяМожет ли кто-нибудь также объяснить, как избежать этого для будущего использования?

[EDIT]

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

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

С помощью трассировки стека вы можете определить, что рекурсия происходит в строке 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) ожидает функцию обратного вызова в качестве второго аргумента, но вместо этого вы передаете результат вызова CheckSource. Вы должны передать CheckSource вместо CheckSource() в качестве второго аргумента:

lmain.after(10, CheckSource)

1 голос
/ 25 сентября 2019

Чтобы сделать это простым способом, вы можете написать инструкцию try / Кроме того, чтобы поймать эту ошибку.Пока вы точно не знаете, в чем заключается ошибка, вы можете использовать функцию catch all, но я бы порекомендовал вам передать конкретную ошибку, как только вы узнаете, что это такое.немного и более точно следовать стандарту PEP8.

Вы действительно должны сделать import tkinter as tk вместо использования *.Это поможет предотвратить перезапись импортированных методов.

Затем ваша лямбда была уничтожена, просто вместо этого выполните root.quit.Мы хотим сохранить ссылку на команду вместо ее выполнения, и мы делаем это, удаляя скобки.Та же проблема существовала с вашим вторым оператором после.

Наконец, вы импортируете PIL, а затем специально импортируете из PIL.Вам не нужно делать оба.Если вам просто нужны Image и ImageTk, просто сделайте from PIL import Image, ImageTk, а если вам нужно много вещей из PIL, тогда вы можете просто сделать import PIL и использовать префикс PIL. оттуда.

ЗдесьВаш очищенный код с оператором try / исключением.Дайте мне знать, если у вас есть какие-либо вопросы.

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...