我正在创建一个将Tkinter GUI与Web抓取相结合的应用程序。 “ searching_window”函数使用两个线程:一个用于较长的过程(Web爬网过程),另一个用于GUI。在GUI上,我使用画布和24帧gif模拟了GIF。我认为遇到的问题是,经过漫长的过程后,我删除了在画布中创建的所有图像,因为在删除它们时会出现24个不同的错误,即图像的确切数量。也许是因为我正在为Tkinter使用线程?但是,错误不会立即出现,我可以去使用下一个GUI窗口,并且在关闭每个Tkinter窗口之后,都会出现错误。
def prev_window():
root = Tk()
root.mainloop()
def next_window():
root = Tk()
root.mainloop()
def searching_window(settings):
def long_process(settings):
...
def app(settings):
def event_gif(n=0):
global timer_id
gif = giflist[n%len(giflist)]
canvas.create_image(gif.width()//2, gif.height()//2, image=gif)
if t1.is_alive():
timer_id = root.after(100, event_gif, n+1)
else:
canvas.delete(ALL)
root.after_cancel(timer_id)
canvas.place_forget()
img_done.place(x=335, y=30)
lbl_done.place(x=330, y=183)
after = utils.number_html_files()
lbl_found.configure(text="I found {} items.".format(after-before))
lbl_found.place(x=217, y=205)
def event_btn(event):
if not t1.is_alive():
root.destroy()
if utils.number_html_files() != 0:
next_window()
gifpath = datapath + "gif"
_ = ["frame_{}.png".format(i) for i in range(1, 25)]
imgfn = "checked.png"
global timer_id
timer_id = "after#0"
before = utils.number_html_files()
root = Tk()
root.geometry("650x300+100+100")
root.title("Searching...")
font = Font(family="Times New Roman", size=15)
font2 = Font(family="Times New Roman", size=12)
background = Label(root, image=smallbackground)
background.image = smallbackground
__ = PhotoImage(file="{}{}".format(gifpath, _[0]))
canvas = Canvas(root, width=300, height=198)
giflist = []
for img in _:
photo = PhotoImage(file="{}{}".format(gifpath, img))
giflist.append(photo)
img_done = Label(root, image=imgfn)
img_done.image = imgfn
lbl_done = Label(root, text="Done!", font=font)
lbl_found = Label(root, font=font, text="I found {} items.")
btn_done = Button(root, text="Continue", font=font)
btn_done.bind("<Button-1>", event_btn)
background.place(x=-1, y=-1)
canvas.place(x=258, y=30)
btn_done.place(x=343, y=235)
root.after(100, event_gif)
root.mainloop()
t1 = threading.Thread(target=long_process, args=[settings])
t2 = threading.Thread(target=app, args=[settings])
t2.start()
t1.start()
t2.join()
t1.join()
以下是错误:
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f0b8>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f0f0>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f128>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f160>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f198>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f1d0>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f208>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f240>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f278>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f2b0>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f2e8>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f320>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f358>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f390>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f3c8>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f400>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f438>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f470>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f4a8>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f4e0>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f518>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f550>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f588>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7fc45c92f5c0>>
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 3507, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
编辑:通过将根创建和主循环移动到定义线程的位置,并在创建新画布之前删除了最后一个画布图像,我修复了该错误:
def prev_window():
root = Tk()
root.mainloop()
def next_window():
root = Tk()
root.mainloop()
def searching_window(settings):
def long_process(settings):
...
def app(settings):
def event_gif(n=0):
global timer_id
gif = giflist[n%len(giflist)]
canvas.delete(ALL)
canvas.create_image(gif.width()//2, gif.height()//2, image=gif)
if t1.is_alive():
timer_id = root.after(100, event_gif, n+1)
else:
canvas.delete(ALL)
root.after_cancel(timer_id)
canvas.place_forget()
img_done.place(x=335, y=30)
lbl_done.place(x=330, y=183)
after = utils.number_html_files()
lbl_found.configure(text="I found {} items.".format(after-before))
lbl_found.place(x=217, y=205)
def event_btn(event):
if not t1.is_alive():
root.destroy()
if utils.number_html_files() != 0:
next_window()
gifpath = datapath + "gif"
_ = ["frame_{}.png".format(i) for i in range(1, 25)]
imgfn = "checked.png"
global timer_id
timer_id = "after#0"
before = utils.number_html_files()
font = Font(family="Times New Roman", size=15)
font2 = Font(family="Times New Roman", size=12)
background = Label(root, image=smallbackground)
background.image = smallbackground
__ = PhotoImage(file="{}{}".format(gifpath, _[0]))
canvas = Canvas(root, width=300, height=198)
giflist = []
for img in _:
photo = PhotoImage(file="{}{}".format(gifpath, img))
giflist.append(photo)
img_done = Label(root, image=imgfn)
img_done.image = imgfn
lbl_done = Label(root, text="Done!", font=font)
lbl_found = Label(root, font=font, text="I found {} items.")
btn_done = Button(root, text="Continue", font=font)
btn_done.bind("<Button-1>", event_btn)
background.place(x=-1, y=-1)
canvas.place(x=258, y=30)
btn_done.place(x=343, y=235)
root.after(100, event_gif)
root = Tk()
root.geometry("650x300+100+100")
root.title("Searching...")
t1 = threading.Thread(target=long_process, args=[settings])
t2 = threading.Thread(target=app, args=[settings])
t2.start()
t1.start()
root.mainloop()
t2.join()
t1.join()