2009-05-17 12 views
44

मैं निम्नलिखित तरीके से उपप्रक्रिया मॉड्यूल का उपयोग करना चाहते हैं:मैं कैसे 'वास्तविक समय की जानकारी वापस एक subprocess.Popen से अजगर में मिलता है (2.5)

  1. है कि संभावित एक नई प्रक्रिया बनाने निष्पादित करने में लंबा समय लगता है।
  2. कब्जा stdout (या stderr, या संभवतः दोनों, या तो एक साथ या अलग से)
  3. उपप्रक्रिया से प्रक्रिया डेटा के रूप में यह में आता है, हर लाइन पर शायद फायरिंग की घटनाओं प्राप्त (wxPython में कहते हैं) या बस उन्हें बाहर मुद्रण अभी के लिए।

मैंने पॉपन के साथ प्रक्रियाएं बनाई हैं, लेकिन अगर मैं संचार का उपयोग करता हूं() प्रक्रिया समाप्त हो जाने के बाद, डेटा एक बार में आता है।

अगर मैं एक अलग थ्रेड कि एक अवरुद्ध myprocess.stdout की readline() (stdout = subprocess.PIPE उपयोग करते हुए) मैं या तो इस विधि के साथ किसी भी लाइनों नहीं मिलता, जब तक प्रक्रिया समाप्त हो जाता है करता है बनाएँ। (कोई फर्क नहीं पड़ता कि मैंने bufsize के रूप में क्या सेट किया है)

क्या इससे डरने का कोई तरीका है जो भयानक नहीं है, और कई प्लेटफार्मों पर अच्छा काम करता है?

+2

myprocess.stdout.readline() को काम करना चाहिए। क्या आप हमें अपना कोड दिखा सकते हैं? –

+0

popen_obj.stdout() से Unbuffered पढ़ना वास्तव में काम करना चाहिए - लेकिन अगर आपको पीटीवी समर्थन के साथ प्लेटफ़ॉर्म तक ही सीमित नहीं है, तो आपका एप्लिकेशन Pexpect लाइब्रेरी के लिए उपयुक्त हो सकता है। –

+1

यह एक अच्छा सवाल है और यह अभी भी "कई प्लेटफॉर्म पर अच्छी तरह से काम करता है" आवश्यकता के लिए अनुत्तरित प्रतीत होता है। –

उत्तर

7

stdout buffered किया जाएगा - तो आपको उस बफर भरने तक कुछ भी नहीं मिलेगा, या उपप्रोसेस निकलता है।

आप उप-प्रक्रिया से stdout फ़्लश करने या stderr का उपयोग करने, या गैर-बफर मोड पर stdout बदलने का प्रयास कर सकते हैं।

+2

क्या इसे डिफ़ॉल्ट रूप से अनबफर नहीं किया जाना चाहिए? कम से कम bufsize = 0 के साथ? – Albert

+2

@ अल्बर्ट: बफर * * सबप्रोसेस के अंदर है, उदाहरण के लिए, 'stdio' buffer। बाल प्रक्रिया के बाहर कुछ भी उस डेटा को तब तक नहीं देखता जब तक कि यह अपने stdout बफर को फ्लश नहीं करता है। यहां [बफरिंग समस्या] के लिए कुछ कामकाज हैं (http://stackoverflow.com/a/20509641/4279) – jfs

2

ऐसा लगता है कि समस्या उपप्रोसेसर द्वारा buffered आउटपुट का उपयोग हो सकती है - अगर अपेक्षाकृत कम मात्रा में आउटपुट बनाया जाता है, तो इसे उपप्रोसेस से बाहर तक बफर किया जा सकता है। कुछ पृष्ठभूमि here पाया जा सकता है: काम करने के लिए नहीं (खिड़कियों पर वैसे भी) प्रतीत होता है कि कोड के साथ

8

अद्यतन

class ThreadWorker(threading.Thread): 
    def __init__(self, callable, *args, **kwargs): 
     super(ThreadWorker, self).__init__() 
     self.callable = callable 
     self.args = args 
     self.kwargs = kwargs 
     self.setDaemon(True) 

    def run(self): 
     try: 
      self.callable(*self.args, **self.kwargs) 
     except wx.PyDeadObjectError: 
      pass 
     except Exception, e: 
      print e 



if __name__ == "__main__": 
    import os 
    from subprocess import Popen, PIPE 

    def worker(pipe): 
     while True: 
      line = pipe.readline() 
      if line == '': break 
      else: print line 

    proc = Popen("python subprocess_test.py", shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) 

    stdout_worker = ThreadWorker(worker, proc.stdout) 
    stderr_worker = ThreadWorker(worker, proc.stderr) 
    stdout_worker.start() 
    stderr_worker.start() 
    while True: pass 
+0

यह स्पष्ट रूप से सबसे अच्छा जवाब है। मुझे पाइथन में यह 'पाइप' प्रकार दिखाने के लिए धन्यवाद! – Mapad

+0

यह एक अच्छा जवाब है, और मेरे लिए काम करता है। कुंजी यह है कि धागे धागे के कारण किसी भी समस्या के बिना ब्लॉक कर सकते हैं। –

+0

'जबकि सत्य: time.sleep (1)' आपके सभी CPU का उपभोग करने वाले व्यस्त प्रतीक्षा लूप से बेहतर है। – ReneSac

2

यहाँ क्या मेरे लिए काम किया है:

cmd = ["./tester_script.bash"] 
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
while p.poll() is None: 
    out = p.stdout.readline() 
    do_something_with(out, err) 

आपके मामले में आप अपने कार्यकर्ता धागा करने के लिए उप-प्रक्रिया के लिए एक संदर्भ गुजरती हैं, और धागे के अंदर मतदान करने की कोशिश कर सकता है। मुझे नहीं पता कि यह कैसे व्यवहार करेगा जब दो धागे एक ही उपप्रोसेशन (और साथ बातचीत) करते हैं, लेकिन यह काम कर सकता है।

यह भी ध्यान दें कि while p.poll() is None: का इरादा है। इसे while not p.poll() के साथ प्रतिस्थापित करें जैसा कि पाइथन 0 (सफल समाप्ति के लिए रिटर्नकोड) को False माना जाता है।

+0

मुझे यकीन नहीं है कि यहां कुछ ऐसा है जो मुझे याद आ रहा है लेकिन ऐसा लगता है कि आपका कोड वास्तव में अवरुद्ध हो रहा है: "जबकि" लूप का अर्थ है कि जो भी फ़ंक्शन का आउटपुट होना चाहिए, वह पीपीओएल तक वापस नहीं किया जाएगा() कोई नहीं है। – pgcd

+0

हां। यह अवरुद्ध है। मुझे लगता है कि जब मैंने इसका उत्तर दिया, तो मैंने सवाल के थ्रेडिंग हिस्से को नहीं देखा। फिर भी, मेरा जवाब यहां "अद्यतित" नहीं है। मुख्य समस्या यह है कि आउटपुट buffered (जैसा कि अन्यत्र उल्लेख किया गया है), और मैं इसका उल्लेख यहां नहीं करता हूं। मैं इसे यहां पोस्टरिटी के लिए छोड़ दूंगा, लेकिन अन्य सबमिट किए गए उत्तर बेहतर हैं। – exhuma

1

मैं भी इस समस्या में भाग रहा हूं। समस्या तब होती है क्योंकि आप stderr को भी पढ़ने की कोशिश कर रहे हैं। अगर कोई त्रुटि नहीं है, तो stderr से पढ़ने की कोशिश ब्लॉक होगा।

विंडोज़ पर, मतदान() फ़ाइल डिस्क्रिप्टर (केवल विंसॉक सॉकेट) के लिए कोई आसान तरीका नहीं है।

तो समाधान एक समाधान से कोशिश करने और पढ़ने के लिए नहीं है।

1

गैर-अवरुद्ध रीडलाइन के साथ pexpect [http://www.noah.org/wiki/Pexpect] का उपयोग इस समस्या को हल करेगा। यह इस तथ्य से उत्पन्न होता है कि पाइपों को बफर किया जाता है, और इसलिए आपके ऐप का आउटपुट पाइप द्वारा बफर किया जा रहा है, इसलिए जब तक बफर भरता है या प्रक्रिया मर जाती है तब तक आप उस आउटपुट तक नहीं पहुंच सकते हैं।

1

यह एक प्रसिद्ध पायथन सीमा प्रतीत होता है, PEP 3145 और शायद अन्य देखें। एक समय में

1

पढ़ें एक चरित्र: http://blog.thelinuxkid.com/2013/06/get-python-subprocess-output-without.html

import contextlib 
import subprocess 

# Unix, Windows and old Macintosh end-of-line 
newlines = ['\n', '\r\n', '\r'] 
def unbuffered(proc, stream='stdout'): 
    stream = getattr(proc, stream) 
    with contextlib.closing(stream): 
     while True: 
      out = [] 
      last = stream.read(1) 
      # Don't loop forever 
      if last == '' and proc.poll() is not None: 
       break 
      while last not in newlines: 
       # Don't loop forever 
       if last == '' and proc.poll() is not None: 
        break 
       out.append(last) 
       last = stream.read(1) 
      out = ''.join(out) 
      yield out 

def example(): 
    cmd = ['ls', '-l', '/'] 
    proc = subprocess.Popen(
     cmd, 
     stdout=subprocess.PIPE, 
     stderr=subprocess.STDOUT, 
     # Make all end-of-lines '\n' 
     universal_newlines=True, 
    ) 
    for line in unbuffered(proc): 
     print line 

example() 
+0

ऐसा लगता है कि यह एक डुप्लिकेट उत्तर है। [मेरी पिछली टिप्पणी] देखें (http: // stackoverflow।com/प्रश्न/803,265/रही-वास्तविक समय-उत्पादन-का उपयोग कर-उपप्रक्रिया/15,288,921 # comment41473849_15288921) – jfs

0

subprocess.Popen का उपयोग करना, मैं अपने सी # परियोजनाओं में से एक की .exe चलाने के लिए और मेरी अजगर फाइल करने के लिए उत्पादन अनुप्रेषित कर सकते हैं। मैं अब पाइथन कंसोल पर print() सी # कंसोल (Console.WriteLine() का उपयोग करके) की सभी जानकारी आउटपुट करने में सक्षम हूं।

अजगर कोड:

from subprocess import Popen, PIPE, STDOUT 

p = Popen('ConsoleDataImporter.exe', stdout = PIPE, stderr = STDOUT, shell = True) 

while True: 
    line = p.stdout.readline() 
    print(line) 
    if not line: 
     break 

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

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