如何解决 Tkinter 中的多处理问题?
How to solve Problem with Multiprocessing in Tkinter?
在这里,我在 tkinter 中使用多重处理 运行 多种算法。起初我尝试使用线程,但它不能在我的程序中正常工作。下面是我的程序工作流程的一个想法,它的工作原理是这样的,但只是功能不同:
from tkinter import *
from multiprocessing import Process
def SquarFunc(Square):
for i in range(1,1000):
Square.set(str(i**2))
def CubeFunc(Cube):
for i in range(1,1000):
Cube.set(str(i**3))
if __name__ == "__main__":
window= Tk()
Square= StringVar()
Cube= StringVar()
window.geometry("500x500")
A= Label(window, textvariable= Square)
A.place(x=200, y=200)
B= Label(window, textvariable= Cube)
B.place(x=300, y=300)
Squaring= Process(target=SquarFunc, args=(Square, ))
Cubing= Process(target=CubeFunc, args=(Cube, ))
Squaring.start()#Error originates here
Cubing.start()
Squaring.join()
Cubing.join()
window.mainloop()
产生的错误是这样的:
TypeError: cannot pickle '_tkinter.tkapp' object
有人知道如何解决这个问题吗??提前致谢!
这里是一个使用 multiprocessing
时如何与其他进程通信的示例(解释在注释中,time.sleep
仅用于示例,否则这些循环将在几微秒内完成):
from tkinter import Tk, StringVar, Label
from multiprocessing import Process, Manager
import time
def square_func(d, name):
for i in range(1, 1000):
# update data in the shared dict
d[name] = i
time.sleep(0.1)
def cube_func(d, name):
for i in range(1, 1000):
# update data in the shared dict
d[name] = i
time.sleep(0.1)
def update_string_vars(d, *variables):
for var in variables:
# get the value from shared dict
value = d[str(var)]
if value is not None:
# set string var to the value
var.set(str(value))
# schedule this to run again
window.after(100, update_string_vars, d, *variables)
# cleanup process upon closing the window in case
# processes haven't finished
def terminate_processes(*processes):
for p in processes:
p.terminate()
if __name__ == "__main__":
window = Tk()
window.geometry("500x500")
# bind the terminator to closing the window
window.bind('<Destroy>', lambda _: terminate_processes(
square_process, cube_process))
square_var = StringVar()
cube_var = StringVar()
Label(window, text='Square:').pack()
Label(window, textvariable=square_var).pack()
Label(window, text='Cube:').pack()
Label(window, textvariable=cube_var).pack()
# create the manager to have a shared memory space
manager = Manager()
# shared dict with preset values as to not raise a KeyError
process_dict = manager.dict({str(square_var): None, str(cube_var): None})
square_process = Process(
target=square_func, args=(process_dict, str(square_var))
)
cube_process = Process(
target=cube_func, args=(process_dict, str(cube_var))
)
square_process.start()
cube_process.start()
# start the updater
update_string_vars(process_dict, square_var, cube_var)
window.mainloop()
有用:
另请参阅:
我强烈建议在导入内容时不要使用通配符 (*
),您应该导入您需要的内容,例如from module import Class1, func_1, var_2
等等或导入整个模块:import module
然后你也可以使用别名:import module as md
或类似的东西,关键是不要导入所有东西,除非你真的知道你在做什么;名称冲突是问题所在。
我强烈建议关注 PEP 8 - Style Guide for Python Code。函数和变量名称应在 snake_case
中,class 中的名称应在 CapitalCase
中。如果用作关键字参数 (func(arg='value')
) 的一部分,则在 =
周围不要有 space,但如果用于 =
,则在 space 周围赋值 (variable = 'some value'
)。在运算符周围有 space(+-/
等:value = x + y
(此处除外 value += x + y
))。在函数和 class 声明周围有两个空行。对象方法定义周围有一个空行。
在这里,我在 tkinter 中使用多重处理 运行 多种算法。起初我尝试使用线程,但它不能在我的程序中正常工作。下面是我的程序工作流程的一个想法,它的工作原理是这样的,但只是功能不同:
from tkinter import *
from multiprocessing import Process
def SquarFunc(Square):
for i in range(1,1000):
Square.set(str(i**2))
def CubeFunc(Cube):
for i in range(1,1000):
Cube.set(str(i**3))
if __name__ == "__main__":
window= Tk()
Square= StringVar()
Cube= StringVar()
window.geometry("500x500")
A= Label(window, textvariable= Square)
A.place(x=200, y=200)
B= Label(window, textvariable= Cube)
B.place(x=300, y=300)
Squaring= Process(target=SquarFunc, args=(Square, ))
Cubing= Process(target=CubeFunc, args=(Cube, ))
Squaring.start()#Error originates here
Cubing.start()
Squaring.join()
Cubing.join()
window.mainloop()
产生的错误是这样的:
TypeError: cannot pickle '_tkinter.tkapp' object
有人知道如何解决这个问题吗??提前致谢!
这里是一个使用 multiprocessing
时如何与其他进程通信的示例(解释在注释中,time.sleep
仅用于示例,否则这些循环将在几微秒内完成):
from tkinter import Tk, StringVar, Label
from multiprocessing import Process, Manager
import time
def square_func(d, name):
for i in range(1, 1000):
# update data in the shared dict
d[name] = i
time.sleep(0.1)
def cube_func(d, name):
for i in range(1, 1000):
# update data in the shared dict
d[name] = i
time.sleep(0.1)
def update_string_vars(d, *variables):
for var in variables:
# get the value from shared dict
value = d[str(var)]
if value is not None:
# set string var to the value
var.set(str(value))
# schedule this to run again
window.after(100, update_string_vars, d, *variables)
# cleanup process upon closing the window in case
# processes haven't finished
def terminate_processes(*processes):
for p in processes:
p.terminate()
if __name__ == "__main__":
window = Tk()
window.geometry("500x500")
# bind the terminator to closing the window
window.bind('<Destroy>', lambda _: terminate_processes(
square_process, cube_process))
square_var = StringVar()
cube_var = StringVar()
Label(window, text='Square:').pack()
Label(window, textvariable=square_var).pack()
Label(window, text='Cube:').pack()
Label(window, textvariable=cube_var).pack()
# create the manager to have a shared memory space
manager = Manager()
# shared dict with preset values as to not raise a KeyError
process_dict = manager.dict({str(square_var): None, str(cube_var): None})
square_process = Process(
target=square_func, args=(process_dict, str(square_var))
)
cube_process = Process(
target=cube_func, args=(process_dict, str(cube_var))
)
square_process.start()
cube_process.start()
# start the updater
update_string_vars(process_dict, square_var, cube_var)
window.mainloop()
有用:
另请参阅:
我强烈建议在导入内容时不要使用通配符 (*
),您应该导入您需要的内容,例如from module import Class1, func_1, var_2
等等或导入整个模块:import module
然后你也可以使用别名:import module as md
或类似的东西,关键是不要导入所有东西,除非你真的知道你在做什么;名称冲突是问题所在。
我强烈建议关注 PEP 8 - Style Guide for Python Code。函数和变量名称应在 snake_case
中,class 中的名称应在 CapitalCase
中。如果用作关键字参数 (func(arg='value')
) 的一部分,则在 =
周围不要有 space,但如果用于 =
,则在 space 周围赋值 (variable = 'some value'
)。在运算符周围有 space(+-/
等:value = x + y
(此处除外 value += x + y
))。在函数和 class 声明周围有两个空行。对象方法定义周围有一个空行。