Tkinter 和多处理

Tkinter and multiprocessing

我有一个调用另一个模块的模块,我在其中使用 tkinter 和一个按钮初始化 canvas。当用户单击按钮时,它会从第一个模块启动一个功能。但是这个函数很长,我不想在函数完全执行之前冻结 tkinter。似乎多处理将是解决方案,但我在实施它时遇到了一些困难。

在第一个模块中:

tkinterModule.initialize(functionFromMainModule)

在第二个模块中:

...
button = Button(master, 
                 text="Launch Function", 
                 command=partial(play, callback))

def play(callback=None):
     if callback is not None:
         callback()

然后在第一个模块中:

def functionFromMainModule():
    ....
    if __name__ == '__main__':
        p = multiprocessing.Process(target=longFunction)
        p.start()

def longFunction():
    ...

但是它并没有启动 longFunction,而是重新初始化了一个新的 tkinter canvas 而没有启动函数。如果我只是调用该函数而不使用多处理,该函数将被正常调用(但 tkinter 会被冻结直到执行结束)。

这个问题的一个可能的解决方案是使用线程。 Python 有一个名为线程的模块。您可以使用此模块创建线程,这样您的 tkinter 应用程序就不会冻结。这是它的样子。

import threading

def Function(Data):
   print(Data)

thread = threading.Thread(target=Function, args=["Hi"], daemon=True).start()

# daemon simply means that the thread will die once done executing.

我们创建一个名为thread的线程。线程将执行该函数。线程将程序同时划分为 运行 个任务。换句话说,这意味着两个或多个任务可以同时 运行。同一进程中的线程使用相同的内存和资源,而进程则不同。您还可以使用线程模块在 classes 中创建线程。只需导入线程模块并在 class 中继承它。例如,

import threading

class Animal(threading.Thread):
    def __init__(self, v):

        threading.Thread.__init__(self, Variable):  # init for threaded classes
        self.Variable = Variable
        self.Run()
    def Run(self):
        print("I am an animal")


A = Animal("Snake")

A.start()

如果您希望对象在不减慢您的应用程序并使其崩溃和冻结的情况下运行,这是一件很棒的事情。

嗯 我想,你在 windows,所以你的问题是当一个新进程开始时,Python 是 pickle-ing 模块(或包)中的所有代码(这是因为windowsrestrictions)

因此,当您使用多处理模块时,您应该使用 if __name__ == '__main__': 语句。原因如下:

当你的代码被 pickle 后,它会在另一个进程中运行,除了 __name__ 变量之外,与主进程完全相同。该变量可以将运行程序中的代码保存为main。由于此错误,您的程序会清除 canvas,然后从头开始工作。