2009-08-15 11 views
5

मैं subprocess.Popen(...) के माध्यम से शुरू की गई लंबी-आश दौड़ प्रक्रिया से stdout को कैप्चर करना चाहता हूं, इसलिए मैं stdout=PIPE का उपयोग एक तर्क के रूप में कर रहा हूं।पायथन - पॉपन स्टडआउट कैप्चर करें और कंसोल पर प्रदर्शित करें?

हालांकि, क्योंकि यह एक लंबी चल रही प्रक्रिया है क्योंकि मैं स्क्रिप्ट के उपयोगकर्ता को स्क्रिप्ट के लिए भेजना चाहता हूं (जैसे कि मैंने इसे पाइप नहीं किया था) ताकि स्क्रिप्ट के उपयोगकर्ता को यह विचार हो कि यह अभी भी काम कर रहा है।

क्या यह सब संभव है?

चीयर्स।

+0

डुप्लिकेट: http://stackoverflow.com/questions/803265/getting-realtime-output-using-subprocess और http : //stackoverflow.com/questions/874815/how-do-i-get-real-time-information-back-from-a-subprocess-popen-in-python-2-5 –

+0

संबंधित: [पायथन: स्ट्रीमिंग पढ़ें subprocess.communicate()] से इनपुट (http://stackoverflow.com/a/17698359/4279) – jfs

उत्तर

1

क्या आप इसे print कर सकते हैं जैसे आप इसे पाइप से पढ़ते हैं?

+0

आह! (लाइट बल्ब पल!) - पी। स्टडआउट ऑब्जेक्ट की तरह एक फाइल है। तो मुझे बस लूप में रीडलाइन() को कॉल करने की आवश्यकता है? सही? लूप से बाहर निकलने का सबसे अच्छा तरीका क्या है - जब p.stdout खाली स्ट्रिंग देता है? क्या मुझे अभी भी सुनिश्चित करने के बाद p.wait() करना चाहिए? –

+1

@ स्टेव: एक खाली स्ट्रिंग पढ़ने से वापस लौटा।stdout का मतलब है कि बच्चे ने अपने stdout बंद कर दिया है, लेकिन यह जरूरी नहीं है कि यह समाप्त हो गया है। p.wait() इसे समाप्त करने की प्रतीक्षा करेगा। – RichieHindle

5

आपकी लंबी चल रही उप-प्रक्रिया बफरिंग शायद आपके कंसोल आउटपुट को झटकेदार और बहुत खराब यूएक्स बनाती है। मेरा सुझाव है कि आप इस तरह के बफरिंग को हराने के लिए pexpect (या, विंडोज, wexpect पर) का उपयोग करने पर विचार करें और उप-प्रक्रिया से चिकनी, नियमित आउटपुट प्राप्त करें।

>>> import pexpect 
>>> child = pexpect.spawn('/bin/bash -c "echo ba; sleep 1; echo bu"', logfile=sys.stdout); x=child.expect(pexpect.EOF); child.close() 
ba 
bu 
>>> child.before 
'ba\r\nbu\r\n' 

बा और बू उचित समय (उन दोनों के बीच एक दूसरे के बारे में) के साथ आ जाएगा: उदाहरण (, pexpect स्थापित करने के बाद बस किसी भी यूनिक्स-y प्रणाली के बारे में पर) के लिए। ध्यान दें कि आउटपुट सामान्य टर्मिनल प्रोसेसिंग के अधीन नहीं है, इसलिए कैरिज रिटर्न वहां पर छोड़े गए हैं - आपको स्वयं स्ट्रिंग को पोस्ट-प्रोसेस करने की आवश्यकता होगी (केवल एक साधारण .replace! -) यदि आपको \n की आवश्यकता है तो अंत में मार्कर (प्रसंस्करण की कमी केवल तभी महत्वपूर्ण होती है जब उप-प्रक्रिया बाइनरी डेटा को अपने stdout पर लिख रही हो - यह सुनिश्चित करता है कि सभी डेटा के बाएं बरकरार हैं! -)।

1

वैकल्पिक रूप से, आप अपनी प्रक्रिया को टी में पाइप कर सकते हैं और केवल एक स्ट्रीम को कैप्चर कर सकते हैं। sh -c 'process interesting stuff' | tee /dev/stderr की लाइनों के साथ कुछ।

बेशक, यह केवल यूनिक्स जैसी प्रणालियों पर काम करता है।

+1

दुर्भाग्यवश अभी भी बफरिंग के कारण झटके के अधीन है :-(। –

2
Getting realtime output using subprocess को

एस लोट की टिप्पणी अंक और Real-time intercepting of stdout from another process in Python

मैं उत्सुक है कि एलेक्स के जवाब यहाँ अपने जवाब से अलग है 1085071. मेरे दो अन्य संदर्भित सवाल में जवाब के साथ सरल छोटे प्रयोगों अच्छे परिणाम दे दी है हूँ ...

मैं गया और ऊपर दिए गए एलेक्स के जवाब के अनुसार हमलावर को देखा, लेकिन मुझे कोड में टिप्पणियां पढ़ने के लिए कहना है कि मुझे इसका उपयोग करने के बारे में बहुत अच्छी भावना नहीं छोड़ी गई थी।

मुझे लगता है कि मेटा-प्रश्न यहां है जब pexpect/wexpect शामिल बैटरी में से एक होगा?

1

ऊपर कहीं pty.openpty() सुझाव से प्रेरित, python2.6, linux पर परीक्षण किया। प्रकाशित कर रहा है, क्योंकि यह कुछ समय लिया इस ठीक से काम कर, w/ओ बफरिंग बनाने के लिए ...

def call_and_peek_output(cmd, shell=False): 
    import pty, subprocess 
    master, slave = pty.openpty() 
    p = subprocess.Popen(cmd, shell=shell, stdin=None, stdout=slave, close_fds=True) 
    os.close(slave) 
    line = "" 
    while True: 
     try: 
      ch = os.read(master, 1) 
     except OSError: 
      # We get this exception when the spawn process closes all references to the 
      # pty descriptor which we passed him to use for stdout 
      # (typically when it and its childs exit) 
      break 
     line += ch 
     sys.stdout.write(ch) 
     if ch == '\n': 
      yield line 
      line = "" 
    if line: 
     yield line 

    ret = p.wait() 
    if ret: 
     raise subprocess.CalledProcessError(ret, cmd) 

for l in call_and_peek_output("ls /", shell=True): 
    pass 
संबंधित मुद्दे