Python 使用tkinter按钮终止多进程池
我正在构建一个应用程序,根据用户输入的内容进行数千(可能数百万)计算。因为这些计算可能需要很长时间,所以我想使用Python的多处理模块。这是我的困境;我想设置一个带有取消按钮的tkinter窗口,以停止在我使用Pool设置的处理器中运行的计算。我尝试使用线程来允许弹出窗口运行,但在运行代码时发生了一些有趣的事情 当我按下“开始”按钮时,游泳池开始按预期运行。然而,我的弹出窗口不会显示,即使它在自己的线程上。更奇怪的是,当我告诉我的IDE(PyCharm)停止程序时,弹出窗口显示,计算仍在运行,直到我从弹出窗口按下“退出”按钮,或者完全终止程序 所以我的问题是:为什么我的弹出窗口即使在自己的线程上也不会显示?我是否正确使用了多处理模块?还是问题完全不同Python 使用tkinter按钮终止多进程池,python,multithreading,tkinter,multiprocessing,Python,Multithreading,Tkinter,Multiprocessing,我正在构建一个应用程序,根据用户输入的内容进行数千(可能数百万)计算。因为这些计算可能需要很长时间,所以我想使用Python的多处理模块。这是我的困境;我想设置一个带有取消按钮的tkinter窗口,以停止在我使用Pool设置的处理器中运行的计算。我尝试使用线程来允许弹出窗口运行,但在运行代码时发生了一些有趣的事情 当我按下“开始”按钮时,游泳池开始按预期运行。然而,我的弹出窗口不会显示,即使它在自己的线程上。更奇怪的是,当我告诉我的IDE(PyCharm)停止程序时,弹出窗口显示,计算仍在运行,
import tkinter as tk
from tkinter import ttk
import random
import threading
import time
from multiprocessing import Pool
def f(x):
print(x*x)
time.sleep(random.randrange(1,5)) # simulates long calculations
# Extra math stuff here...
def processor():
global calc
calc = Pool(4)
calc.map(f, [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30])
print("Done")
def calculation_start():
p = threading.Thread(target=progress_window) # Thread to open a new window for the user to cancel a calculation
p.start()
processor() # Calls the function to run the calculations
def progress_window():
# This is the window that pops up to let a user cancel a calculation.
popup = tk.Toplevel()
endButton = ttk.Button(popup, text="End", command=lambda :(calc.terminate()))
endButton.pack()
master = tk.Tk()
startButton = ttk.Button(master, text="Start", command=calculation_start)
startButton.pack()
tk.mainloop()
编辑:
我尝试将处理器
函数切换到线程,而不是进程窗口
函数
def calculation_start():
p = threading.Thread(target=processor) # Thread for the function to run the calculations
p.start()
progress_window() # Open a new window for the user to cancel a calculation
我的弹出窗口出现,按下“结束”按钮时,它看起来会停止处理器,但它不会继续超过该点。就像它卡在processor()函数中的calc.map(f[1,2,3,…]
。来自文档:
def calculation_start():
p = threading.Thread(target=processor) # Thread for the function to run the calculations
p.start()
progress_window() # Open a new window for the user to cancel a calculation
它将阻塞,直到结果就绪
这意味着,是的,工作正在其他线程上完成,但是主线程(调用map
的线程)在其他线程完成之前不会执行任何其他操作。您希望使用并(对于长时间运行的交互式进程)提供一个回调,以便在池完成时执行什么操作(可能隐藏弹出窗口)
如果希望程序只显示弹出窗口然后退出,则需要使用map\u async
返回的。在空闲后使用设置空闲处理程序(请参阅并记住,每次调用后都需要手动重新添加处理程序)。在每次空闲调用后,可以调用AsyncResult.ready()
或AsyncResult.get()
查看池是否已完成。一旦完成,您就可以安全地处理结果并退出。尝试在master=tk.tk()之前添加如果uuuu name\uuuuu=='\uuu main\uuuu':
并缩进它和后面的其他行。@martineau感谢您的建议,但它仍然遇到相同的问题。1.启动进程池一次2.在这种情况下不要使用线程3.要在池完成给定任务时收到通知,请将更新GUI的回调传递到池。应用异步,池.map_async
我为map_async
关闭了map
,它立即运行回调并在回调后继续运行代码。但是,它不会等待池完成或通过代码继续终止(回拨也是如此。它一开始就被调用)。它应该这样做吗?有没有办法让它等到完成或终止?更新后的答案会处理您的跑步然后退出场景。