gpt4 book ai didi

python - 在 Tkinter 中使用 root.after 和 root.mainloop 的正确方法

转载 作者:太空宇宙 更新时间:2023-11-04 07:18:40 25 4
gpt4 key购买 nike

我有一个 tkinter 界面,需要每 5 分钟自动刷新一次。到目前为止没有问题,您只需要执行以下操作:

root.after(300000, function_to_run, args_of_fun_to_run)

问题是我必须在“无限”时间内执行此操作。场景是 GUI 将在连接到电视的 PC 上运行,在我的办公室全天候 24/7 显示一些信息。这工作了大约 8 个小时,然后我收到以下错误:

enter image description here

现在,我知道回溯一直到我的一个使用 matplotlib 的自定义模块中的一行。我的自定义模块都没有使用任何循环,所以我知道错误不是直接来自其中一个(如果我错了请纠正我),所以它一定是我无限次地重复这个函数。这是我的主要功能的代码:

from tkinter import *
from tkinter import ttk
import logging
import datetime
import sys

sys.path.append(r'C:\Users\me\Desktop\seprated sla screens')

import sla_main as sla
import main_frame as mf
import sla_grid as sg
import incoming_volume as iv
import outgoing_volume as ov
import read_forecast as fc
import get_headers as hd
import vol_graph as vg
import out_graph as og
import add_graph as ag
import sla_reduction_email as sre

###################################
###################################
###################################
###################################

runs = 0

def maininterface(f_size, pic_x, pic_y):

global runs
global root

start = str(datetime.datetime.now().date()) + ' ' + str(datetime.timedelta(hours=6))

screen = sla.slamain(start)

if runs == 0:
root = mf.mainframe(f_size)

sg.sla_grid(screen, f_size, root)

file = open('titles in queue.txt', 'r')

in_q = file.read()

file.close

ttk.Label(root, text=in_q, anchor=CENTER, width=15, font=('times', f_size, 'bold')).grid(column=6, row=2, sticky=E)

if runs > 0:

###################################
#deletes all rows before making the calculations
for label in root.grid_slaves():
if int(label.grid_info()["row"]) > 1:
label.grid_forget()

sg.sla_grid(screen, f_size, root)

file = open('titles in queue.txt', 'r')

in_q = file.read()

file.close

ttk.Label(root, text=in_q, anchor=CENTER, width=15, font=('times', f_size, 'bold')).grid(column=6, row=2, sticky=E)




###################################
#all this part is just info for the graph and the graph

incoming = iv.incomingvolume(start)

outgoing = ov.outgoingvolume(start)

forecast = fc.readforecast()

headers = hd.getheaders()

vg.volgraph(forecast, incoming, headers, pic_x, pic_y)

#og.outgraph(forecast, outgoing, headers, pic_x, pic_y)

ag.addgraph("vol_graph.png", root, 1)

#ag.addgraph("out_graph.png", root, 2)

runs = runs + 1

globals().update(locals())

print(str(datetime.datetime.now()))

root.after(300000, maininterface, f_size, pic_x, pic_y)

root.mainloop()




logging.basicConfig(level=logging.DEBUG, filename='error_log.txt')

try:
maininterface(28, 23.5, 6)

except:
logging.exception("Oops:")

我可以在这里修改什么来避免这个错误?

谢谢!

编辑:

正如许多人所建议的那样,我已将 mainloop 调用移到 main 函数之外。我的最后几行代码现在看起来像这样:

try:
maininterface(28, 23.5, 6)
root.mainloop()

except:
logging.exception("Oops:")

root.after 调用保留在函数内。这样运行后,5分钟后关闭。有谁知道为什么没有调用主循环?

最佳答案

如何使用mainloopafter

简而言之,正确的方法是确保您调用 mainloop 一次,然后让您的周期函数在完成工作后重新安排自身:

root = tk.Tk()
...
def do_one_iteration():
... your code here ...
root.after(300000, do_one_iteration)

root.mainloop()

移除递归

您的代码中的问题是您在调用 after 的同一函数中调用了 mainloop - 您在每次迭代期间创建了一个无限循环你的无限循环。这是问题的直接原因。您需要将对 mainloop 的调用移出 maininterface 函数,以便它只被调用一次。

修复内存泄漏

您还需要稍微重构一下maininterface。看起来您一直在创建新的小部件而没有销毁旧的小部件,这是内存泄漏。最终你的程序会耗尽内存。当然,每五分钟只创建一个新小部件并不算过分,但对于必须全天候 24 小时运行的应用来说,它会随着时间的推移而增加。

通常最好只是更新现有的小部件,而不是销毁并重新创建它们,但如果是这样,您需要做的不仅仅是调用 grid_forget。所做的只是将它们从 View 中移除,但它们仍在占用内存。如果您真的想删除旧的小部件,请调用 destroy 方法。

正确关闭文件

您显然是在尝试使用 file.close 关闭文件,但正确的语法是 file.close()(注意尾随的括号)

关于python - 在 Tkinter 中使用 root.after 和 root.mainloop 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29376970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com