2010-11-19 8 views
7

पर पाइथन मल्टीप्रोसेसिंग प्रोसेस आउटपुट कैसे भेज सकता हूं मैं टिंकर गुई में प्रदर्शित एक अजगर मल्टीप्रोसेसिंग प्रक्रिया से आउटपुट प्राप्त करने का प्रयास कर रहा हूं।मैं टिथरर गुई

मैं प्रक्रियाओं से उत्पादन एक जीयूआई के माध्यम से एक कमांड खोल करने के लिए, उदाहरण के लिए एक खोल प्रॉम्प्ट पर fllowing छोटे स्क्रिप्ट चलाने से भेज सकते हैं:

from multiprocessing import Process 
import sys 

def myfunc(text):  
    print text 
    sys.stdout.flush() 

def f1(): 
    p1 = Process(target = myfunc, args = ("Surprise",)) 
    p1.start() 

def f2(): 
    p2 = Process(target = myfunc, args = ("Fear",)) 
    p2.start() 

def fp(): 
    myfunc("... and an almost fanatical devotion to the Pope") 

a = Tk() 

b1 = Button(a, text="Process 1", command=f1) 
b1.grid(row=0, column=0, pady=10, padx=10, sticky=SE) 
b2 = Button(a, text="Process 2", command=f2) 
b2.grid(row=0, column=1, pady=10, padx=10, sticky=SE) 
b3 = Button(a, text="Parent", command=fp) 
b3.grid(row=0, column=2, pady=10, padx=10, sticky=SE) 

if __name__ == "__main__": 
    a.mainloop() 

मैं भी एक के लिए माता पिता से उत्पादन भेज सकते हैं पाठ बॉक्स, myfunc

# sys.stdout.flush() 

में stdout की फ्लशिंग बाहर टिप्पणी और बाद तुरंत जोड़ने "b3.grid ..." से ऊपर संशोधित करके उदाहरण के लिए लाइन निम्नलिखित:

class STDText(Text): 
    def __init__(self, parent, cnf={}, **kw): 
     Text.__init__(self, parent, cnf, **kw) 
    def write(self, stuff): 
     self.config(state=NORMAL) 
     self.insert(END, stuff) 
     self.yview_pickplace("end") 
     self.config(state=DISABLED) 

messages = STDText(a, height=2.5, width=30, bg="light cyan", state=DISABLED) 
messages.grid(row=1, column=0, columnspan=3) 
sys.stdout = messages 

हालांकि मैं यह नहीं समझ सकता कि प्रक्रियाओं से पाठ बॉक्स में आउटपुट कैसे भेजना है। क्या मुझे कुछ आसान याद आ रही है?

उत्तर

8

आप stdout/stderr को अनुप्रेषित सकता है myfunc() में एक स्ट्रिंगियो, फिर उस स्ट्रिंगियो में जो कुछ भी लिखा जाता है उसे माता-पिता को भेजें (जैसा कि unutbu द्वारा सुझाया गया है)। इस पुनर्निर्देशन के एक तरीके के लिए this question पर मेरा उत्तर देखें।

#!/usr/bin/env python 
import sys 
from cStringIO import StringIO 
from code import InteractiveConsole 
from contextlib import contextmanager 
from multiprocessing import Process, Pipe 

@contextmanager 
def std_redirector(stdin=sys.stdin, stdout=sys.stdin, stderr=sys.stderr): 
    tmp_fds = stdin, stdout, stderr 
    orig_fds = sys.stdin, sys.stdout, sys.stderr 
    sys.stdin, sys.stdout, sys.stderr = tmp_fds 
    yield 
    sys.stdin, sys.stdout, sys.stderr = orig_fds 

class Interpreter(InteractiveConsole): 
    def __init__(self, locals=None): 
     InteractiveConsole.__init__(self, locals=locals) 
     self.output = StringIO() 
     self.output = StringIO() 

    def push(self, command): 
     self.output.reset() 
     self.output.truncate() 
     with std_redirector(stdout=self.output, stderr=self.output): 
      try: 
       more = InteractiveConsole.push(self, command) 
       result = self.output.getvalue() 
      except (SyntaxError, OverflowError): 
       pass 
      return more, result 

def myfunc(conn, commands): 
    output = StringIO() 
    py = Interpreter() 
    results = "" 

    for line in commands.split('\n'): 
     if line and len(line) > 0: 
      more, result = py.push(line + '\n') 
      if result and len(result) > 0: 
       results += result 

    conn.send(results) 
    conn.close() 

if __name__ == '__main__': 
    parent_conn, child_conn = Pipe() 

    commands = """ 
print "[42, None, 'hello']" 

def greet(name, count): 
    for i in range(count): 
     print "Hello, " + name + "!" 

greet("Beth Cooper", 5) 
fugazi 
print "Still going..." 
""" 
    p = Process(target=myfunc, args=(child_conn, commands)) 
    p.start() 
    print parent_conn.recv() 
    p.join() 

सुरक्षा यहाँ पर लागू (यानी, जब तक आप ऐसा नहीं करते हैं के बारे में सामान्य चेतावनियां:

के बाद से है कि उदाहरण के एक बिट से अधिक आप की जरूरत है, यहाँ एक संस्करण है कि और अधिक द्वारा अपने निर्धारित लक्ष्यों के अनुरूप है बेवकूफ/दुर्भावनापूर्ण कुछ भी नहीं करने के लिए इन कोड स्निपेट के प्रेषक पर भरोसा कर सकते हैं)।

यह भी ध्यान रखें कि यदि आप पाइथन अभिव्यक्ति और कथनों के मनमाने ढंग से मिश्रण की व्याख्या करने की आवश्यकता नहीं है तो आप इसे बहुत सरल बना सकते हैं। यदि आपको केवल कुछ शीर्ष-स्तरीय फ़ंक्शन को कॉल करने की आवश्यकता है जो कुछ आउटपुट उत्पन्न करते हैं, तो कुछ ऐसा अधिक उपयुक्त हो सकता है:

def dosomething(): 
    print "Doing something..." 

def myfunc(conn, command): 
    output = StringIO() 
    result = "" 
    with std_redirector(stdout=output, stderr=output): 
     try: 
      eval(command) 
      result = output.getvalue() 
     except Exception, err: 
      result = repr(err) 

    conn.send(result) 
    conn.close() 

if __name__ == '__main__': 
    parent_conn, child_conn = Pipe() 
    command = "dosomething()" 
    p = Process(target=myfunc, args=(child_conn, command)) 
    p.start() 
    print parent_conn.recv() 
    p.join() 
3

आप multiprocessing.Pipe का उपयोग कर प्रक्रियाओं के बीच डेटा (पिकलेबल) पास कर सकते हैं। उदाहरण के लिए:

import Tkinter 
import multiprocessing as mp 

class STDText(Tkinter.Text): 
    def __init__(self, parent, cnf={}, **kw): 
     Tkinter.Text.__init__(self, parent, cnf, **kw) 
    def write(self, stuff): 
     self.config(state=Tkinter.NORMAL) 
     self.insert(Tkinter.END, stuff) 
     self.yview_pickplace("end") 
     self.config(state=Tkinter.DISABLED) 

def myfunc(conn,text):  
    conn.send(text) 
    conn.close() 

class Gui(object): 
    def __init__(self): 
     self.a=Tkinter.Tk() 
     b1=Tkinter.Button(self.a, text="Process 1", command=self.foo) 
     b1.grid(row=0, column=0, pady=10, padx=10, sticky=Tkinter.SE) 
     b2=Tkinter.Button(self.a, text="Process 2", command=self.bar) 
     b2.grid(row=0, column=1, pady=10, padx=10, sticky=Tkinter.SE) 
     b3=Tkinter.Button(self.a, text="Parent", command=self.baz) 
     b3.grid(row=0, column=2, pady=10, padx=10, sticky=Tkinter.SE) 
     self.messages=STDText(
      self.a, height=2.5, width=30, bg="light cyan", state=Tkinter.DISABLED) 
     self.messages.grid(row=1, column=0, columnspan=3) 
     self.a.mainloop()   
    def call_myfunc(self,text): 
     parent_conn, child_conn=mp.Pipe() 
     proc=mp.Process(target=myfunc, args=(child_conn,text,)) 
     proc.start() 
     self.messages.write(parent_conn.recv()) 
     proc.join()  
    def foo(self): 
     self.call_myfunc('Foo\n') 
    def bar(self): 
     self.call_myfunc('Bar\n')   
    def baz(self): 
     parent_conn, child_conn=mp.Pipe() 
     myfunc(child_conn,'Baz\n') 
     self.messages.write(parent_conn.recv()) 

if __name__ == "__main__": 
    Gui() 

अधिक जानकारी के लिए multiprocessing पर Doug Hellman's tutorial देखें।

+0

Unutbu - बहुत उपयोगी उत्तर के लिए धन्यवाद। यह निश्चित रूप से मेरे खिलौना उदाहरण हल करता है। (वास्तविक अनुप्रयोग में प्रक्रियाएं अलग-अलग फ़ंक्शंस चलाती हैं और आउटपुट संदेशों को स्वचालित रूप से उत्पन्न करती हैं (यानी पैरामीटर के रूप में उन्हें दिए गए कुछ विशिष्ट पाठ को मुद्रित नहीं करते हैं)। मैंने सोचा था कि पाइप में आने से बचने के लिए 'सस्ता' ढूंढना संभव था या नहीं, लेकिन मुझे लगता है कि शायद जाने का रास्ता है। – tchaz

0

कि myfunc मान लिया जाये कि इस प्रक्रिया के उत्पादन के साथ कहा जाता है, जैसे myfunc लिखें:

def myfunc(text):  
    textwidget.insert("end", text) 

जहां textwidget पाठ विजेट के लिए एक संभाल है

+0

सुझाव के लिए धन्यवाद। यह निश्चित रूप से मेरे खिलौने के उदाहरण में मदद करेगा। हालांकि, मुझे शायद थोड़ा अधिक चाहिए जो मुझे चाहिए - असली एप्लिकेशन में प्रक्रियाएं विभिन्न कार्यों को चलाएंगी और आउटपुट संदेश उत्पन्न करेंगी स्वचालित रूप से (यानी पैरामीटर के रूप में उन्हें दिए गए कुछ विशिष्ट पाठ को प्रिंट नहीं करना)। – tchaz

संबंधित मुद्दे