Multithreading 在python3中从multiprocess.process更新tk ProgressBar

Multithreading 在python3中从multiprocess.process更新tk ProgressBar,multithreading,python-3.x,progress-bar,tkinter,multiprocessing,Multithreading,Python 3.x,Progress Bar,Tkinter,Multiprocessing,我已经成功地创建了一个线程的线程示例,它可以在运行时更新Progressbar。然而,到目前为止,在多处理中做同样的事情让我感到困惑。 我开始怀疑这样使用tkinter是否可行。有人这样做过吗 我在OSX10.7上运行。环顾四周,我知道不同的操作系统可能表现得非常不同,特别是在多处理和tkinter方面 我尝试了一个生产者,它通过名称空间和event.wait以及event.set直接与小部件对话。我也做过同样的事情,一个生产者和一个消费者交谈,这是一个与小部件交谈的方法或函数。所有这些东西都成

我已经成功地创建了一个线程的线程示例,它可以在运行时更新Progressbar。然而,到目前为止,在多处理中做同样的事情让我感到困惑。 我开始怀疑这样使用tkinter是否可行。有人这样做过吗

我在OSX10.7上运行。环顾四周,我知道不同的操作系统可能表现得非常不同,特别是在多处理和tkinter方面

我尝试了一个生产者,它通过名称空间和event.wait以及event.set直接与小部件对话。我也做过同样的事情,一个生产者和一个消费者交谈,这是一个与小部件交谈的方法或函数。所有这些东西都成功运行,但不会直观地更新小部件。虽然我在IntVar上做了一个get(),但是当使用widget.step()和/或widget.set()时,widget被绑定到并看到它发生了变化。我甚至尝试在子进程内运行一个单独的tk()实例。没有任何内容更新进度栏

这是一个更简单的版本。子进程是一个对象上的方法,该对象是Progressbar小部件的包装器。TKGUI作为主进程运行。我还发现小部件在循环结束时没有被破坏有点奇怪,这可能是我不理解其含义的一个线索

import multiprocessing
from tkinter import *
from tkinter import ttk
import time

root = Tk()

class main_window:

    def __init__(self):
        self.dialog_count = 0

        self.parent = root
        self.parent.title('multiprocessing progess bar')

        frame = ttk.Labelframe(self.parent)
        frame.pack(pady=10, padx=10)

        btn = ttk.Button(frame, text="Cancel")
        btn.bind("<Button-1>", self.cancel)
        btn.grid(row=0, column=1, pady=10)

        btn = ttk.Button(frame, text="progress_bar")
        btn.bind("<Button-1>", self.pbar)
        btn.grid(row=0, column=2, pady=10)

        self.parent.mainloop()

    def pbar(self, event):

        name="producer %d" % self.dialog_count
        self.dialog_count += 1

        pbar = pbar_dialog(self.parent, title=name)

        event = multiprocessing.Event()
        p = multiprocessing.Process(target=pbar.consumer, args=(None, event))

        p.start()



    def cancel(self, event):
       self.parent.destroy()



class pbar_dialog:

    toplevel=None
    pbar_count = 0

    def __init__(self, parent, ns=None, event=None, title=None, max=100):
        self.ns = ns
        self.pbar_value = IntVar()
        self.max = max

        pbar_dialog.pbar_count += 1
        self.pbar_value.set(0)


        if not pbar_dialog.toplevel:
            pbar_dialog.toplevel= Toplevel(parent)

        self.frame = ttk.Labelframe(pbar_dialog.toplevel, text=title)
        #self.frame.pack()
        self.pbar = ttk.Progressbar(self.frame, length=300, variable=self.pbar_value)
        self.pbar.grid(row=0, column=1, columnspan=2, padx=5, pady=5)

        btn = ttk.Button(self.frame, text="Cancel")
        btn.bind("<Button-1>", self.cancel)
        btn.grid(row=0, column=3, pady=10)
        self.frame.pack()


    def set(self,value):
        self.pbar_value.set(value)

    def step(self,increment=1):
        self.pbar.step(increment)
        print ("Current", self.pbar_value.get())

    def cancel(self, event):
       self.destroy()

    def destroy(self):
        self.frame.destroy()
        pbar_dialog.pbar_count -= 1
        if pbar_dialog.pbar_count == 0:
            pbar_dialog.toplevel.destroy()

    def consumer(self, ns, event): 
        for  i in range(21):
            #event.wait(2)
            self.step(5)
            #self.set(i)
            print("Consumer", i)
        self.destroy()



if __name__ == '__main__':
    main_window()
导入多处理
从tkinter进口*
从tkinter导入ttk
导入时间
root=Tk()
类主窗口:
定义初始化(自):
self.dialog\u count=0
self.parent=root
self.parent.title('多处理进程栏')
frame=ttk.Labelframe(self.parent)
框架组件(pady=10,padx=10)
btn=ttk.按钮(框,text=“取消”)
btn.bind(“,self.cancel)
btn.网格(行=0,列=1,pady=10)
btn=ttk.按钮(框,text=“进度条”)
btn.bind(“,self.pbar)
btn.网格(行=0,列=2,pady=10)
self.parent.mainloop()
def pbar(自身、事件):
name=“生产者%d”%self.dialog\u计数
self.dialog_count+=1
pbar=pbar\U对话框(self.parent,title=name)
事件=多处理。事件()
p=multiprocessing.Process(target=pbar.consumer,args=(无,事件))
p、 开始()
def取消(自我,事件):
self.parent.destroy()
类pbar_对话框:
顶层=无
pbar_计数=0
def u u init u;(self,parent,ns=None,event=None,title=None,max=100):
self.ns=ns
self.pbar_value=IntVar()
self.max=max
pbar_dialog.pbar_计数+=1
self.pbar_值设置(0)
如果不是pbar_dialog.toplevel:
pbar_对话框。顶级=顶级(父级)
self.frame=ttk.Labelframe(pbar_dialog.toplevel,text=title)
#self.frame.pack()
self.pbar=ttk.Progressbar(self.frame,长度=300,变量=self.pbar_值)
self.pbar.grid(行=0,列=1,列span=2,padx=5,pady=5)
btn=ttk.按钮(self.frame,text=“取消”)
btn.bind(“,self.cancel)
btn.网格(行=0,列=3,pady=10)
self.frame.pack()
def设置(自身,值):
self.pbar_value.set(值)
def步骤(自,增量=1):
自功率步进(增量)
打印(“当前”,self.pbar\u value.get())
def取消(自我,事件):
自我毁灭
def销毁(自我):
self.frame.destroy()
pbar\u dialog.pbar\u计数-=1
如果pbar\u dialog.pbar\u count==0:
pbar_dialog.toplevel.destroy()
def耗电元件(自身、ns、事件):
对于范围(21)内的i:
#事件。等待(2)
自我保护。步骤(5)
#自我设定(一)
印刷品(“消费者”,i)
自我毁灭
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
主窗口()
相比之下,这是一个非常好用的线程版本。

import threading
from tkinter import *
from tkinter import ttk
import time

root = Tk()

class main_window:

    def __init__(self):
        self.dialog_count = 0

        self.parent = root
        self.parent.title('multiprocessing progess bar')

        frame = ttk.Labelframe(self.parent)
        frame.pack(pady=10, padx=10)

        btn = ttk.Button(frame, text="Cancel")
        btn.bind("<Button-1>", self.cancel)
        btn.grid(row=0, column=1, pady=10)

        btn = ttk.Button(frame, text="progress_bar")
        btn.bind("<Button-1>", self.pbar)
        btn.grid(row=0, column=2, pady=10)

        self.parent.mainloop()


    def producer(self, pbar):
        i=0
        while i < 101:
            time.sleep(1)
            pbar.step(1)
            i += 1
        pbar.destroy()


    def pbar(self, event):

        name="producer %d" % self.dialog_count
        self.dialog_count += 1

        pbar = pbar_dialog(self.parent, title=name)

        p = threading.Thread(name=name, target=self.producer, args=(pbar,))

        p.start()

        #p.join()


    def cancel(self, event):
       self.parent.destroy()



class pbar_dialog:

    toplevel=None
    pbar_count = 0

    def __init__(self, parent, ns=None, event=None, title=None, max=100):
        self.ns = ns
        self.pbar_value = IntVar()
        self.title = title
        self.max = max

        pbar_dialog.pbar_count += 1

        if not pbar_dialog.toplevel:
            pbar_dialog.toplevel= Toplevel(parent)

        self.frame = ttk.Labelframe(pbar_dialog.toplevel, text=title)
        #self.frame.pack()
        self.pbar = ttk.Progressbar(self.frame, length=300, variable=self.pbar_value)
        self.pbar.grid(row=0, column=1, columnspan=2, padx=5, pady=5)

        btn = ttk.Button(self.frame, text="Cancel")
        btn.bind("<Button-1>", self.cancel)
        btn.grid(row=0, column=3, pady=10)
        self.frame.pack()

        self.set(0)

    def set(self,value):
        self.pbar_value.set(value)

    def step(self,increment=1):
        self.pbar.step(increment)

    def cancel(self, event):
       self.destroy()

    def destroy(self):
        self.frame.destroy()
        pbar_dialog.pbar_count -= 1
        if pbar_dialog.pbar_count == 0:
            pbar_dialog.toplevel.destroy()
            pbar_dialog.toplevel = None

    def automatic(self, ns, event): 
        for i in range(1,100):
            self.step()

if __name__ == '__main__':
    main_window()
导入线程
从tkinter进口*
从tkinter导入ttk
导入时间
root=Tk()
类主窗口:
定义初始化(自):
self.dialog\u count=0
self.parent=root
self.parent.title('多处理进程栏')
frame=ttk.Labelframe(self.parent)
框架组件(pady=10,padx=10)
btn=ttk.按钮(框,text=“取消”)
btn.bind(“,self.cancel)
btn.网格(行=0,列=1,pady=10)
btn=ttk.按钮(框,text=“进度条”)
btn.bind(“,self.pbar)
btn.网格(行=0,列=2,pady=10)
self.parent.mainloop()
def发生器(自身、pbar):
i=0
而我<101:
时间。睡眠(1)
pbar.步骤(1)
i+=1
pbar.destroy()
def pbar(自身、事件):
name=“生产者%d”%self.dialog\u计数
自对话\u计数+=1
pbar=pbar\U对话框(self.parent,title=name)
p=threading.Thread(name=name,target=self.producer,args=(pbar,))
p、 开始()
#p、 加入
def取消(自我,事件):
self.parent.destroy()
类pbar_对话框:
顶层=无
pbar_计数=0
def u u init u;(self,parent,ns=None,event=None,title=None,max=100):
self.ns=ns
self.pbar_value=IntVar()
self.title=标题
self.max=max
pbar_dialog.pbar_计数+=1
如果不是pbar\u对话框。顶层:
pbar_对话框。顶级=顶级(父级)
self.frame=ttk.Labelframe(pbar_dialog.toplevel,text=title)
#self.frame.pack()
self.pbar=ttk.Progressbar(self.frame,长度=300,变量=self.pbar_值)
self.pbar.grid(行=0,列=1,列span=2,padx=5,pady=5)
btn=ttk.按钮(self.frame,text=“取消”)
btn.bind(“,self.cancel)
btn.网格(行=0,列=3,pady=10)
self.frame.pack()
self.set(0)
def设置(自身,值):
self.pbar_value.set(值)
def步骤(自,增量=1):
自功率步进(增量)
def取消(自我,事件):
自我毁灭
def销毁(自我):
self.frame.de
# -*- coding: utf-8 -*-
# threadsandprocesses.py

# Importing modules
import time
import threading
import multiprocessing
import Tkinter as tki
import ttk


class Master(object):
    def __init__(self):
        self.mainw = tki.Tk()
        self.mainw.protocol("WM_DELETE_WINDOW", self.myclose)
        self.mainw.title("Progressbar")
        self.mainw.geometry('300x100+300+300')
        self.main = tki.Frame(self.mainw)
        self.RunButton = ttk.Button(self.main, text='Run',
                                    command=self.dostuff)
        self.EntryBox = ttk.Entry(self.main)
        self.EntryBox.insert(0, "Enter a number")
        self.progress = ttk.Progressbar(self.main,
                                        mode='determinate', value=0)
        self.main.pack(fill=tki.BOTH, expand=tki.YES)
        self.progress.pack(expand=tki.YES)
        self.EntryBox.pack(expand=tki.YES)
        self.RunButton.pack()
        print "The Master was created"

    def dostuff(self):
        print "The Master does no work himself"
        data = range(int(self.EntryBox.get()))
        S = Slave(self, data)
        print "The Master created a Slave to do his stuff"
        print "The Slave gets told to start his work"
        S.start()

    def myclose(self):
        self.mainw.destroy()
        return

    def nextstep(self):
        print "Good job, Slave, I see the result is"
        print Master.results.get()


class Slave(threading.Thread):
    def __init__(self, guest, data):
        print "This is the Slave."
        print "Nowdays, Work is outsourced!"
        self.data = data
        self.guest = guest
        threading.Thread.__init__(self)

    def run(self):
        print "The Slave is outsourcing his work to Calcualte inc."
        time.sleep(1)
        Outsourcing = Calculate()
        Results = Outsourcing.run(self.guest, self.data)
        return Results


# unwrapping outside a class
def calc(arg, **kwarg):
    return Calculate.calculate(*arg, **kwarg)


class Calculate(object):

    def run(self, guest, data):
        print"This is Calculate inc. ... how can I help you?"
        time.sleep(1)
        maximum = int(guest.EntryBox.get())
        guest.progress.configure(maximum=maximum, value=0)
        manager = multiprocessing.Manager()
        queue = manager.Queue()
        lock = manager.Lock()
        print "Things are setup and good to go"
        # Counting the number of available CPUs in System
        pool_size = multiprocessing.cpu_count()
        print "Your system has %d CPUs" % (pool_size)
        # Creating a pool of processes with the maximal number of CPUs possible
        pool = multiprocessing.Pool(processes=pool_size)
        Master.results = pool.map_async(calc, (zip([self]*len(data), [lock]*len(data),
                                        [queue]*len(data), data)))
        for job in range(1, maximum+1):
            queue.get()  # this is an abuse I think, but works for me
            guest.progress.configure(value=job)
        # Properly close and end all processes, once we're done
        pool.close()
        pool.join()
        print "All done"
        guest.nextstep()
        return

    def calculate(self, lock, queue, indata):
        lock.acquire()
        print 'Reading values and starting work'
        lock.release()
        time.sleep(3)  # some work
        results = indata  # The works results
        lock.acquire()
        print 'Done'
        lock.release()
        queue.put("Finished!")
        return results

if __name__ == '__main__':
    TheMaster = Master()
    TheMaster.mainw.mainloop()