Pyinstaller,每个 joblib 并行调用都会在 MacOS 上创建一个新的 tkinter window

Pyinstaller, every joblib Parallel call creates a new tkinter window on MacOS

这里是可以重现问题的代码(只是为了重现问题,所以做的有点无意义):

from joblib import Parallel, delayed
import tkinter as tk


def f():
    print('func call')


if __name__ == '__main__':
    root = tk.Tk()

    button = tk.Button(root,
                       command=lambda: Parallel(n_jobs=-1, backend='threading')(delayed(f)() for _ in range(1)),
                       text='func')
    button.pack()

    root.mainloop()

上面的代码在我的 IDE 中可以 运行 完美,但是一旦我用 Pyinstaller 创建了一个可执行文件,它就会出错。 创建可执行文件的命令行如下:

pyinstaller -F main.py

异常行为是,每次按下 tkinter window 中的按钮时,应在终端中打印一个 func call 字符串。但是当我使用可执行文件运行时,每次按下按钮,除了在终端中打印外,还会创建一个新的tkinter window。

我也曾尝试使用相同的命令在 Windows 中构建可执行文件。可执行文件 运行 在 Windows 中很好(按下按钮时没有创建新的 tkinter window)。只有macOS平台有这个问题

我应该如何解决这个问题?

这是我遇到问题的平台:

在代码中加入multiprocessing.freeze_support()问题解决。固定版本代码如下:

import multiprocessing
multiprocessing.freeze_support()

from joblib import Parallel, delayed
import tkinter as tk


def f():
    print('func called')


if __name__ == '__main__':
    root = tk.Tk()

    button = tk.Button(root,
                       command=lambda: Parallel(n_jobs=-1, backend='threading')(delayed(f)() for _ in range(1)),
                       text='func')
    button.pack()

    root.mainloop()

感谢 rokm 回答我关于 GitHub 的问题,这是 URL 到 rokm 的 答案: https://github.com/pyinstaller/pyinstaller/issues/6852#issuecomment-1138269358.