我刚刚为我正在创建的一个工作项目解决了这个问题。galbendavid提供的答案确实有效,但仅适用于具有单一窗口的应用程序。这是因为tkinter.Tk根是在应用程序初始化时创建的,而不是在脚本底部的condition语句下创建的。所以支持用户1683793把它放在正确的位置。只要root是一个全局变量,就可以很容易地使用它生成具有相同根对象的其他窗口。在
以下面的项目根目录为例。在root/
├── __main__.py
└── myapp/
├── __init__.py
├── core.py
├── datatypes.py
└── gui.py
忽略myapp包的__init__.py文件,有两个模块容纳了这些模块
应用程序的用户界面:保存主窗口的myapp.core模块和包含核心容器使用的所有组件的myapp.gui模块。考虑到更改类意味着更改模块本身,重新加载整个模块更有意义,因此在运行时始终使用最新版本。在
要在不重新启动程序的情况下重新加载应用程序GUI,所使用的进程必须:重新加载已编辑的模块(通常使用importlib.reload)
使用来自旧对象的信息从新模块的内容构建新对象。
确保将任何其他对象/属性的所有权转移到新对象。在
取消对旧对象的引用以进行垃圾回收。这包括旧模块以及与之相关的所有类和函数。在
根/myapp/核心.py
首先,您需要一个容器类,它与GUI组件的其余部分完全隔离。最好从中开始并能够返回空的默认状态,这是当您在编辑root/myapp/gui.py之后尝试重新加载其组件时将保留的状态。此默认状态将只保留菜单栏,其中所有重新加载命令都存储在运行时菜单中。在
^{pr2}$
reload_window和{}方法分别重新加载应用程序的核心模块和组件模块。在
reload_window然后在重新加载的myapp.core中搜索与当前应用程序类同名的类,从新类创建一个新对象,并销毁旧的应用程序窗口。在
reload_components从底层容器中删除所有组件,然后重新运行build_components。因为import语句是从build_components内声明的,它将始终使用重新加载的模块的最新版本。在
根/myapp/图形用户界面.py
此模块将包含myapp.core模块使用的所有GUI组件。在from tkinter import *
class AppFrame(Frame):
def __init__(self, master=None):
Frame.__init__(self, master=master)
...
根目录/主目录页
最后,使用目录顶部的__main__.py,您可以运行应用程序并重新加载应用程序的特定部分,而无需完全重新启动程序。唯一显式引用的用户代码是启动时的myapp.core.Application。在from tkinter import Tk
#Module Setup Code
...
def create_application(master):
#Keep all imports to reloadable dependencies in
#the local scope to use the most recent version
from myapp.core import Application
return Application(master=root)
if __name__ == '__main__':
root = Tk()
app = create_application(root)
app.mainloop()
注意:为了尽可能高效地工作,您应该将重新加载的模块的任何导入都本地化为使用它们的函数,直到您完成对这些模块的编辑。根据您使用的加载器的不同,如果全局导入,以这种方式多次重新加载模块可能会使同一模块的多个版本在整个程序中延迟。在本地导入时,除了sys.modules中的引用之外,不会保留对模块的活动引用。然后,在重新加载期间替换的任何未引用模块都将可用于垃圾回收。在
如果这对您来说是不可能的,一种解决方法是包含一个函数force_update(self, module),该函数搜索对旧模块版本内容的引用,并使用映射到模块最新版本的引用创建一个新对象。找到旧模块甚至不需要这样做。检查一个函数是否是最新的可以简单如下。在def force_update(self, module):
func = self.attr_func
same = func.__module__ == module.__name__
newfunc = getattr(module, func.__name__)
if same and func != newfunc:
self.attr_func = newfunc
return self