python tkinter mainloop,如何处理tkinter mainloop中的错误?

I have a python program which is scraping web data for a client. tkinter is used for the interface. Outline is:

Window 1 lets the user select what information to scrape.

Window 1 closes

Separate thread is started for the scraper. This thread will in turn spawn more threads to allow multiple pages to be downloaded at once.

Window 2 opens to show download progress (e.g. "downloading client 5 of 17")

User closes Window 2 to end program.

The program will work for the first few hundred pages, but then it starts spitting out the error message:

Traceback (most recent call last):

File "C:\Users\Me\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 248, in __del__

if self._tk.getboolean(self._tk.call("info", "exists", self._name)):

RuntimeError: main thread is not in main loop

Exception ignored in: >

multiple times until all the threads have been stopped. No idea what could be causing this error. The actual code is:

import scraper, threading

import tkinter as tk

from queue import Queue

outputQueue = Queue()

class OutputRedirect(object):

def __init__():

super().__init__()

def write(self, string):

outputQueue.put(string)

def getInformation():

stdout = sys.stdout

sys.stdout = OutputRedirect()

scraper.startThreads()

scraper.startPulling()

sys.stdout = stdout

def updateTextField(window, root):

if not outputQueue.empty():

string = outputQueue.get()

window.textArea.insert("insert", string)

outputQueue.task_done()

root.after(1, updateTextField, window, root)

'''widget/window definitions - not important'''

guiInfo = {"stuff1": [], "stuff2": []}

root = tk.Tk()

window1 = Window1(root, guiInfo)

window1.mainloop()

pullThread = threading.Thread(target=pullClaims,

args=(list(guiInfo["stuff1"]),

list(guiInfo["stuff2"])), daemon=True)

pullThread.start()

root = tk.Tk()

window2 = Window2(root)

root.after(0, updateTextField, window2, root)

window2.mainloop()

The scraper program (which works fine on its own) uses print statements for user feedback. Rather than re-write everything, I just pointed stdout to a queue. The main thread uses the "after" function to check on the queue a few times a second. If there is anything in it then it gets printed to the Text widget on the window.

I've put try/catch just about everywhere in the code, but they haven't caught a thing. I'm convinced the problem is in the mainloop itself, but I can't find any up to date information for how to stick something new in it. Any help would be greatly appreciated.

解决方案

To handle tkinter errors you do the following

class TkErrorCatcher:

'''

In some cases tkinter will only print the traceback.

Enables the program to catch tkinter errors normally

To use

import tkinter

tkinter.CallWrapper = TkErrorCatcher

'''

def __init__(self, func, subst, widget):

self.func = func

self.subst = subst

self.widget = widget

def __call__(self, *args):

try:

if self.subst:

args = self.subst(*args)

return self.func(*args)

except SystemExit as msg:

raise SystemExit(msg)

except Exception as err:

raise err

import tkinter

tkinter.CallWrapper = TkErrorCatcher

But in your case please do not do this. This should only ever be done in the case of wanting to hide error messages from your users in production time. As commented above you have a nono's going on.

To spawn multiple windows you can use tkinter.Toplevel

I would recommend in general to read

and for your specific problem of threading in tkinter this blog post nails it. Basically you need to have the tkinter mainloop blocking the programs main thread, then use after calls from other threads to run other code in the mainloop.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值