如何解决 Tkinter 中的多处理问题?
Posted
技术标签:
【中文标题】如何解决 Tkinter 中的多处理问题?【英文标题】:How to solve Problem with Multiprocessing in Tkinter? 【发布时间】:2021-12-19 11:55:17 【问题描述】:在这里,我使用多处理在 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
有人知道如何解决这个问题吗?提前致谢!
【问题讨论】:
这个答案是否涵盖了您需要的内容:***.com/a/26835188/8382028 如果不是,您需要发布您的代码,而不仅仅是错误 @ViaTech 我已经阅读了那个链接..但我不太明白它的含义,而且它与我的程序有点不同..让我编辑我的帖子并输入代码..谢谢 @ViaTech 我已经发布了我的代码..你知道如何解决它吗? 提供minimal reproducible example而不是你的整个代码,无论如何,你不能在其他进程中使用tkinter
,因为它不可腌制
@Matiiss 好的....
【参考方案1】:
这是一个使用multiprocessing
时如何与其他进程通信的示例(解释在 cmets 中,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()
有用:
Sharing state between processes shortly abouttkinter
and processes
另见:
我强烈建议不要在导入某些内容时使用通配符 (*
),您应该导入您需要的内容,例如from module import Class1, func_1, var_2
等等或导入整个模块:import module
然后你也可以使用别名:import module as md
或类似的东西,关键是不要导入所有东西,除非你真的知道你在做什么;名称冲突是问题所在。
我强烈建议关注PEP 8 - Style Guide for Python Code。函数和变量名应该在snake_case
,类名在CapitalCase
。如果=
用作关键字参数的一部分(func(arg='value')
),则不要在=
周围留有空格,但如果将=
用于分配值(variable = 'some value'
),则在=
周围留有空格。在运算符周围留出空间(+-/
等:value = x + y
(此处除外value += x + y
))。在函数和类声明周围有两个空行。对象方法定义周围有一个空行。
【讨论】:
非常感谢您的解释! 非常感谢您的指导,现在我终于可以在我的竞赛项目中成功实施了。。您介意可以分享一下您的电子邮件地址吗,以便我可以交流我的想法如果我以后有更多的困难,特别是在python编程方面。再次感谢你。以上是关于如何解决 Tkinter 中的多处理问题?的主要内容,如果未能解决你的问题,请参考以下文章
Java 并发编程解析 | 如何正确理解Java领域中的多线程模型,主要用来解决什么问题?