简体   繁体   中英

Python Multiprocessing in a GUI with redirected printing

When performing multiprocessing in python using the Process call, I would like to immediately print a completion statement after completion of each process from the parent process rather than in the child worker function. I am doing this in a Tk GUI, so the sys.stdout is redirected (see simple example version below). If I print inside the worker function (printLetters - uncomment out "#print letter") I get the error: "The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec()."

If someone can suggest a way to fix either of these two issues (identifying when the queue has been updated from the parent process OR a way to print inside a process with sys.stdout redirected), it would be greatly appreciated.

Thanks...

import Tkinter
from Tkinter import *
import multiprocessing
import time
from multiprocessing import Process, Queue

class StringVarFile:
    def __init__(self,stringVar,window):
        self.__newline = 0
        self.__stringvar = stringVar
        self.__window = window
    def write(self,s):
        new = self.__stringvar.get()
        for c in s:
            if self.__newline:
                new = ""; self.__newline = 0
            new = new+c
        self.set(new)
    def set(self,s):
        self.__stringvar.set(s); self.__window.update()   
    def get(self):
        return self.__stringvar.get()
    def flush(self): pass

def executeSomething(letters):
    procs=list()
    queue = Queue()
    print 'Begining letter printing...'
    for letter in letters:
        p = Process(target=printLetters, args=(queue,letter))
        procs.append(p)
        p.start()

    for p in procs:
        p.join()
    print 'Finished printing letters'

def printLetters(queue,letter):
    time.sleep(2)
    #print letter
    queue.put(letter)

if __name__ == '__main__':
    root = Tk()
    statusVar = StringVar() ### Class method for Tkinter. Description: "Value holder for strings variables."
    letters = ['a','b','c','d']

    Label(root,width=50,height=10,textvariable=statusVar).pack()
    sys.stdout = StringVarFile(statusVar,root)
    root.after(100, executeSomething(letters))
    root.mainloop()

Do you just want to print to the GUI? If so, inside executeSomething() between starting and joining the processes, why not just iterate over queue results? Like this:

for letter in letters:
    print queue.get()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM