python TkInter正在囤积越来越多的ram

e3bfsja2  于 2023-04-04  发布在  Python
关注(0)|答案(1)|浏览(159)

我正在创建一个脚本来检查我的一些计算机的状态,但注意到随着时间的推移,Tkinter窗口正在积累越来越多的资源。有什么方法可以解决这个问题吗?

import subprocess
import time
import tkinter as tk
import threading
import gc

ip_addresses = ["192.168.1.83", "192.168.1.93", "192.168.1.93", "192.168.1.92", "192.168.1.95", "192.168.1.103", "192.168.1.105"]
i= 0
if i == 0:
    root = tk.Tk()
    root.title("Online")
    root.geometry("500x300")
    i+1

label_texts = [f"{ip_address} -> unknown" for ip_address in ip_addresses]
labels = [tk.Label(root, text=label_text, font=("Arial", 16), fg="#FF0000") for label_text in label_texts]
for i, label in enumerate(labels):
    label.pack(padx=10, pady=5)

def check_ip_status(ip_address, label):
    try:
        subprocess.check_output(f"ping {ip_address} -n 1", shell=True, timeout=5)
        label.config(text=f"{ip_address} -> online", fg="#00FF00") # Green
    except subprocess.CalledProcessError:
        label.config(text=f"{ip_address} -> offline", fg="#FF0000") # Red
    except subprocess.TimeoutExpired:
        label.config(text=f"{ip_address} -> offline (timeout)", fg="#FFA500") # Orange

def check_all_ip_statuses():
    processes = []
    for i, ip_address in enumerate(ip_addresses):
        label = labels[i]
        process = subprocess.Popen(f"ping {ip_address} -t", shell=True, stdout=subprocess.DEVNULL)
        processes.append(process)
        thread = threading.Thread(target=check_ip_status, args=(ip_address, label))
        thread.start()

    root.after(5000, check_all_ip_statuses) 
    gc.collect() 

    # Close all subprocesses
    for process in processes:
        process.kill()
        process.communicate()

check_all_ip_statuses()
root.mainloop()

我试过强制垃圾收集器,杀死所有进程,并清除标签,但没有什么能阻止tkinter囤积越来越多的内存
------------更新----------
我已经将子进程调用更改为pythonping

import pythonping
import time
import tkinter as tk
import threading
import gc

ip_addresses = ["192.168.1.83", "192.168.1.85", "192.168.1.93", "192.168.1.92", "192.168.1.95", "192.168.1.103", "192.168.1.105"]

i= 0
if i == 0:
    root = tk.Tk()
    root.title("Online")
    root.geometry("500x300")
    i+1

def create_labels():
    global labels
    labels = [tk.Label(root, text=f"{ip_address} -> unknown", font=("Arial", 16), fg="#FF0000") for ip_address in ip_addresses]
    for label in labels:
        label.pack(padx=10, pady=5)

def check_ip_status(ip_address, label):
    response = pythonping.ping(ip_address, count=1, timeout=5)
    if response.success():
        label.config(text=f"{ip_address} -> online", fg="#00FF00") # Green
    else:
        label.config(text=f"{ip_address} -> offline", fg="#FF0000") # Red

def check_all_ip_statuses():
    for i, ip_address in enumerate(ip_addresses):
        label = labels[i]
        thread = threading.Thread(target=check_ip_status, args=(ip_address, label))
        thread.start()

    gc.collect() 
    root.after(1000, check_all_ip_statuses) 

create_labels()
check_all_ip_statuses()
root.mainloop()
ssm49v7z

ssm49v7z1#

当你一遍又一遍地启动你的线程时,每隔一秒,你就会用新的线程填满你的内存,即使当前的线程还没有完成。
这不是垃圾收集的问题,而是等待任务完成,然后再重新启动它们。
所以我把check_all_ip_statuses()改成这样:

def check_all_ip_statuses():
    threads = []
    alive = False
    for thread in threads:
        if thread.is_alive():
            alive = True
            break

    if not alive:
        threads.clear()
        for i, ip_address in enumerate(ip_addresses):
            label = labels[i]
            threads.append(threading.Thread(target=check_ip_status, args=(ip_address, label), daemon=True))
            threads[-1].start()

    gc.collect()
    root.after(500, check_all_ip_statuses)

你应该以守护进程的形式运行线程,否则当你退出应用程序时会出错。现在你可以看到,线程只有在最后一个线程完成ping并准备好进行下一轮之后才重新启动。这将防止你的ram被填满。

**注意:**这可能会减慢你的ping间隔为您添加到列表中的每个ip.但我没有测试这个.

在你的代码中还有一些我不明白的地方,我把它清理了一下。我希望这没问题。

以下是全部来源:

import pythonping
import tkinter as tk
import threading
import gc

ip_addresses = ["192.168.1.83", "192.168.1.85", "192.168.1.93", "192.168.1.92", "192.168.1.95", "192.168.1.103",
                "192.168.1.105"]

def create_labels():
    global labels
    labels = [tk.Label(root, text=f"{ip_address} -> unknown", font=("Arial", 16), fg="#FF0000") for ip_address in
              ip_addresses]
    for label in labels:
        label.pack(padx=10, pady=5)

def check_ip_status(ip_address, label):
    response = pythonping.ping(ip_address, count=1, timeout=5)
    if response.success():
        label.config(text=f"{ip_address} -> online", fg="#00FF00")  # Green
    else:
        label.config(text=f"{ip_address} -> offline", fg="#FF0000")  # Red

def check_all_ip_statuses():
    threads = []
    alive = False
    for thread in threads:
        if thread.is_alive():
            alive = True
            break

    if not alive:
        threads.clear()
        for i, ip_address in enumerate(ip_addresses):
            label = labels[i]
            threads.append(threading.Thread(target=check_ip_status, args=(ip_address, label), daemon=True))
            threads[-1].start()

    gc.collect()
    root.after(500, check_all_ip_statuses)

root = tk.Tk()
root.title("Online")
root.geometry("500x300")
create_labels()
check_all_ip_statuses()
root.mainloop()

相关问题