【问题标题】:Python & tkinter, experiencing a memory leak when opening and closing a dialogPython & tkinter,打开和关闭对话框时遇到内存泄漏
【发布时间】:2017-12-01 00:30:01
【问题描述】:

我正在编写一个 GUI 来与数据库交互。 GUI 要求用户登录。如果尝试连接到数据库失败,我会创建一个错误对话框。我一直在看任务管理器,每次弹出错误对话框,程序使用的内存都会跳一下。我想我可能对 tkinter 有误解。任何帮助表示赞赏。所有相关代码如下。我想我已经指出了LogInWindow.enter_cb() 内的except 的泄漏。我知道这个类没有正确缩进。无法正确格式化文本。

main 函数在 mainloop 上启动 LogInWindow。

from tkinter import *
from tkinter import ttk

class ErrorWindow(Tk):
"""Window for displaying database log in errors"""
def __init__(self, exception):
    Tk.__init__(self)

    self.title('MySQL Error')
    self.resizable(False, False)

    error = Text(self, height=2, wrap=WORD, relief=FLAT)
    error.insert(END, 'MySQL {!r}'.format(exception))
    error.tag_configure("center", justify='center')
    error.tag_add("center", 1.0, "end")
    error.config(state=DISABLED)
    error.configure(bg=self.cget('bg'))
    error.pack(padx=5, pady=(5, 0))

    ok = ttk.Button(self, text='OK', command=self._quit)
    ok.bind('<Return>', self._quit)
    ok.pack(padx=5, pady=5)

    # root.grab_set()
    ok.focus_set()

def _quit(self, *args):
    self.destroy()


class LogInWindow(Tk):
"""Window for getting the user's database credentials"""

connection = None

def __init__(self):
    Tk.__init__(self)

    self.title('Enter Credentials')
    self.resizable(False, False)

    main_frame = ttk.Frame(self)
    main_frame.pack(fill=BOTH, expand=True, padx=20, pady=5)

    entry_frame = ttk.Frame(main_frame)
    entry_frame.pack()

    u_label = ttk.Label(entry_frame, text='Username')
    p_label = ttk.Label(entry_frame, text='Password')
    self.usern = ttk.Entry(entry_frame)
    self.passw = ttk.Entry(entry_frame, show='*')

    self.usern.bind('<Return>', self.enter_cb)
    self.passw.bind('<Return>', self.enter_cb)

    u_label.grid(row=0, column=0, padx=15, pady=5)
    self.usern.grid(row=0, column=1, padx=(0, 15), pady=5)
    p_label.grid(row=1, column=0, padx=15, pady=5)
    self.passw.grid(row=1, column=1, padx=(0, 15), pady=5)

    button_frame = ttk.Frame(self)
    button_frame.pack()

    enter = ttk.Button(button_frame, text='Enter', command=self.enter_cb)
    cancel = ttk.Button(button_frame, text='Cancel', command=self.cancel_cb)

    enter.bind('<Return>', self.enter_cb)
    cancel.bind('<Return>', self.cancel_cb)

    enter.pack(side=LEFT, padx=10, pady=10)
    cancel.pack(side=LEFT, padx=10, pady=10)

    self.usern.focus_set()

def enter_cb(self, *args):
    """Enter callback for either creating a database connection or spewing an error dialog"""
    try:
        # make a conection with the database
        import pymysql.cursors
        self.connection = pymysql.connect(host='localhost',
                                          user=self.usern.get(),
                                          password=self.passw.get(),
                                          db='databasename',
                                          charset='utf8mb4',
                                          cursorclass=pymysql.cursors.DictCursor)
        self.destroy()
    except pymysql.err.OperationalError as e:
        # create an error dialog
        error = ErrorWindow(e)
        center(error)
        error.mainloop()
        # del(error)

def cancel_cb(self, *args):
    """Cancel callback for destroying the window"""
    self.destroy()

【问题讨论】:

  • 您的缩进不正确。请尝试修复它。
  • 是的,我在 OP 中引用了这个,但是我不能将类语句放在代码块中,而不在每一行添加 4 个空格。对不起。有一个更好的方法吗?我没有在 SO 上发帖的经验
  • 您可以突出显示所有代码,然后单击类似于{} 的按钮以缩进四个空格。见meta.stackexchange.com/questions/22186/…
  • 您也可以突出显示所有代码,然后按CTRL+K 获得与按{} 按钮相同的结果。
  • 谢谢。下次会记住提示

标签: python tkinter memory-leaks


【解决方案1】:

至少部分问题在于您不应拥有多个 Tk 实例。如果您正在创建一个对话框,它必须是Toplevel 的子类,而不是Tk。

一个设计良好的 tkinter 程序应该明确地创建一次根窗口 (Tk()),并且只调用一次 mainloop。

【讨论】:

  • 谢谢你,我会做出适当的调整。另一个问题。我的登录窗口是否也应该是Toplevel 的子类,而实际程序是Tk 的子类?我也支持你,我只是没有足够的声誉。 编辑:感谢这解决了我的问题!
  • 我理解Tk和Toplevel之间的关系。再次感谢您的洞察力。
猜你喜欢
  • 2014-08-01
  • 1970-01-01
  • 2023-03-15
  • 2010-11-28
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 2013-05-17
  • 2017-11-16
相关资源
最近更新 更多