在Tkinter GUI中启动多个进程。 (Python 2.7)

时间:2014-12-20 05:02:10

标签: python-2.7 user-interface tkinter multiprocessing pickle

我正在开发一个内部应用程序,用于使用Tkinter进行图像处理/计算机视觉。我过去常常通过一些代码来破解和快速运行,并且用户友好不在我的经验范围内。在启动程序的耗时部分之前,最终用户需要手动设置一些值。

我遇到的问题是:由于正在处理的图像数量,程序需要很长时间(约1小时)。当我将处理分为4个核心时,我看到了显着的加速(大约三分之一的时间)(仅供参考 - 流程之间不需要通信);但是,当我尝试从Tkinter类启动一个新进程时,我收到了错误。

彻底地在我的头上,我已经长期屈服于复制粘贴succubi诱人的诱惑,现在几乎不理解我正在尝试的任何东西。我发现类似的问题herehere,并且实施其中建议的更改会将我的错误换成新的错误。请参阅以下所有错误。

初步尝试:

import Tkinter
from multiprocessing import Manager, Pool

class userApp(Tkinter.Frame):

    def multi_proc(self):
        arg_gen = ((n) for n in self.values)
        manager = Manager()
        self.ret = manager.dict()
        pool = Pool(4)
        jobs = pool.map_async(self.func2, arg_gen)
        self.ret = jobs.get()


    def func1(self):
        self.values = range(15)

    def func2(self,args):
        return("I'm #%d"%(args[0]))

    def _quit(self):
        self.quit()

    def createWidgets(self):
        self.button1 = Tkinter.Button(root,text="Set some values",command=self.func1)
        self.button2 = Tkinter.Button(root,text="Start processes",command=self.multi_proc)
        self.button3 = Tkinter.Button(root,text="Quit",command=self._quit)
        self.button1.pack()
        self.button2.pack()
        self.button3.pack()

   def __init__(self, master=None):
        Tkinter.Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

root = Tkinter.Tk()
root.title("Select an option")
if __name__ == '__main__':
    app = userApp(master=root)
    app.mainloop()
    root.destroy()

这会返回以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Anaconda\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:\...\TestScript.py", line 13, in multi_proc
    self.ret = jobs.get()
  File "C:\Anaconda\lib\multiprocessing\pool.py", line 558, in get
    raise self._value
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

func2()包装在Tk应用之外并将参数发送到包装器会导致不同的pickling错误:

class userApp(Tkinter.Frame):
    ...

    def multi_proc(self):
        arg_gen = ((n) for n in self.values)
        manager = Manager()
        self.ret = manager.dict()
        pool = Pool(4)
        jobs = pool.map_async(unwrap_self_f, zip([self]*len(self.values), arg_gen))
        self.ret = jobs.get()
    ...

def unwrap_self_f(arg, **kwarg):
    return userApp.func2(*arg, **kwarg)

抛出:

... same as before ...
UnpickleableError: Cannot pickle <type 'tkapp'> objects

最后(抱歉这篇长篇文章),将其添加到课程中:

    def __getstate__(self):
        state = self.__dict__.copy()
        del state['view']
        return state

抛出这个:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Anaconda\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:\...\TestScript.py", line 13, in multi_proc
    self.ret = jobs.get()
  File "C:\Anaconda\lib\multiprocessing\pool.py", line 558, in get
    raise self._value
KeyError: 'view'

我知道未来的自我会回顾现在的自我并告诉我,我是一个白痴,但在此期间,任何帮助或方向都会受到赞赏。

0 个答案:

没有答案