You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确配置tkinter的after()函数?网站检测状态提前更新排查

问题出在哪?
  1. 定时任务叠加爆炸:你当前的SiteCheck函数会遍历所有站点,每检测一个有效站点就调用window.after()重新触发整个SiteCheck。比如有3个站点,第一次执行就会生成3个新定时任务,下次执行又会生成更多,直接导致站点状态被疯狂触发更新,远早于你设置的间隔时间。
  2. 网络请求卡死界面:requests.get()是同步阻塞操作,执行时tkinter主界面会直接假死,同时打乱定时任务的执行节奏,时间自然不准。
  3. 缺少输入校验:如果输入的时间不是数字,直接转int会触发报错,程序直接崩溃。
修复方案

核心思路是给每个站点单独维护定时任务,用线程处理网络请求避免阻塞界面,下面是完整修复后的代码:

import tkinter as tk
from tkinter import messagebox
import requests
import threading


class SiteChecker:
    def __init__(self):
        self.window = tk.Tk()
        self.window.geometry('400x700')
        self.window.title("SiteChecker")
        # 存储每个站点的[输入框, 时间框, 状态标签, 定时任务ID]
        self.data_list = []

        self._init_ui()

    def _init_ui(self):
        # 表头设置
        tk.Label(self.window, text="站点地址:").grid(column=0, row=1)
        tk.Label(self.window, text="检测间隔(秒): ").grid(column=1, row=1)
        tk.Label(self.window, text="可用状态 ").grid(column=2, row=1)

        # 初始化4个站点输入行
        for loop in range(2, 6):
            self._add_site_row(loop)

        # 功能按钮
        tk.Button(self.window, text="添加新站点", command=self.add_new_site).grid(column=1, row=0)
        tk.Button(self.window, command=self.start_all_checks, text='开始检测').grid(row=0, column=2)

    def _add_site_row(self, row):
        url_entry = tk.Entry(self.window, width=18)
        url_entry.grid(column=0, row=row, pady=8)

        interval_entry = tk.Entry(self.window, width=3)
        interval_entry.grid(column=1, row=row, pady=8)

        status_label = tk.Label(self.window, text="未检测")
        status_label.grid(column=2, row=row, pady=8)

        # 初始定时任务ID设为0(表示无任务)
        self.data_list.append([url_entry, interval_entry, status_label, 0])

    def add_new_site(self):
        # 获取最后一行的行号+1,作为新行的位置
        last_row = self.data_list[-1][0].grid_info()['row'] + 1
        self._add_site_row(last_row)

    def _check_single_site(self, index):
        url_entry, interval_entry, status_label, old_task_id = self.data_list[index]
        url = url_entry.get().strip()
        interval_str = interval_entry.get().strip()

        # 输入合法性校验
        if not url.startswith('http'):
            status_label.config(text="URL格式错误")
            self._schedule_next_check(index)
            return
        if not interval_str.isdigit():
            status_label.config(text="时间格式错误")
            self._schedule_next_check(index)
            return
        interval = int(interval_str)

        # 子线程执行网络请求,避免阻塞主界面
        def check_task():
            try:
                response = requests.get(url, timeout=10)
                status_label.config(text='正常' if response.status_code == 200 else '异常')
            except Exception:
                status_label.config(text='异常')
            # 回到主线程调度下一次检测
            self.window.after(0, lambda: self._schedule_next_check(index))

        threading.Thread(target=check_task, daemon=True).start()

    def _schedule_next_check(self, index):
        url_entry, interval_entry, status_label, old_task_id = self.data_list[index]
        interval_str = interval_entry.get().strip()
        if not interval_str.isdigit():
            return
        interval = int(interval_str) * 1000

        # 取消之前的定时任务,避免叠加
        if old_task_id != 0:
            self.window.after_cancel(old_task_id)

        # 创建新的定时任务,保存任务ID
        new_task_id = self.window.after(interval, lambda: self._check_single_site(index))
        self.data_list[index][3] = new_task_id

    def start_all_checks(self):
        # 启动所有站点的首次检测
        for idx in range(len(self.data_list)):
            self._check_single_site(idx)

    def run(self):
        self.window.mainloop()


if __name__ == "__main__":
    app = SiteChecker()
    app.run()
关键改动点
  • 独立定时任务:每个站点单独维护定时任务ID,每次调度前取消旧任务,彻底解决任务叠加导致的提前更新问题。
  • 线程处理网络请求:把requests.get()放到子线程执行,主界面不会假死,定时任务的执行节奏也能保证准确。
  • 输入校验:增加URL和时间格式的校验,非法输入会直接提示错误,避免程序崩溃。
  • 逻辑拆分:把单个站点的检测、调度逻辑独立出来,代码结构更清晰,后续维护也方便。

内容的提问来源于stack exchange,提问作者EvgeniyMEV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:55:40