Python& tkinter,在打开和关闭对话框时遇到内存泄漏

时间:2017-06-27 20:06:46

标签: python tkinter memory-leaks

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

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()

1 个答案:

答案 0 :(得分:2)

问题的至少一部分是你不应该只有一个Tk个实例。如果要创建对话框,则它必须是Toplevel的子类,而不是Tk

设计良好的tkinter程序应该只显式创建一次根窗口(Tk()),然后只调用mainloop一次。