2011-02-09 14 views
15

से प्रगति संदेश प्राप्त करना मैं एक प्रोग्राम शुरू करना चाहता हूं जिसे पूरा होने में कई मिनट की आवश्यकता है। इस समय के दौरान मैं कार्यक्रम के प्रगति संदेश को पढ़ना चाहता हूं (जो stdout पर मुद्रित हैं)। समस्या यह है कि मुझे अपने रन के दौरान अपने आउटपुट को पढ़ने का कोई तरीका नहीं मिल रहा है।एक उपप्रोसेसर

एक प्रोग्राम के आउटपुट को पढ़ने के लिए मैंने पाया एकमात्र फ़ंक्शन Popen.communicate() है, लेकिन यह विधि प्रक्रिया समाप्त होने तक प्रतीक्षा करती है। इसलिए प्रगति प्राप्त करना असंभव है और इसे उपयोगकर्ता को विशेष रूप से स्वरूपित तरीके से दिखाना असंभव है।

क्या यह एक और तरीका करना संभव है?

जब मैं अपनी स्क्रिप्ट के साथ subprocess.popen के साथ प्रक्रिया चलाता हूं तो मुझे स्क्रीन पर प्रोग्राम का आउटपुट दिखाई देता है। क्या इसे छिपाना संभव है? (उबंटू 10.10, सामान्य टर्मिनल)

उत्तर

15

सरलता कीवर्ड तर्क stdout=subprocess.PIPE के साथ पॉपन को कॉल करना सरल है।

p = subprocess.Popen(["ls"], stdout=subprocess.PIPE) 
while True: 
    line = p.stdout.readline() 
    if not line: 
     break 
    print line 

कार्रवाई में यह देखने के लिए, यहां दो नमूना स्क्रिप्ट कर रहे हैं। उन दोनों को एक ही निर्देशिका में बनाने और चलाने के python superprint.py

printandwait.py:

import time 
import sys 
print 10 
sys.stdout.flush() 
time.sleep(10) 
print 20 
sys.stdout.flush() 

superprint.py:

import subprocess 
import sys 
p = subprocess.Popen(["python printandwait.py"], shell=True, stdout=subprocess.PIPE) 
while True: 
    print "Looping" 
    line = p.stdout.readline() 
    if not line: 
     break 
    print line.strip() 
    sys.stdout.flush() 
+0

यदि लूप को तोड़ने के बाद कुछ डेटा आता है तो क्या होगा? – Neo

+1

@ नीओ: उसका उदाहरण ईओएफ पर टूट जाता है, जिसका मतलब है कि उसके बाद कोई और डेटा नहीं आ सकता है। लेकिन, अपने प्रश्न के निहितार्थ का उत्तर देने के लिए: यदि आप stdout पाइप को नहीं पढ़ते हैं, तो बफर भर सकता है और उपप्रोसेस stdout लिखने का प्रयास अवरुद्ध कर देगा। – payne

+0

यह बाद में उपयोग करने के लिए p.stdout में आपके लिए इंतजार कर रहा होगा। हालांकि जब तक नया इनपुट नहीं आता है या पाइप बंद हो जाता है तब तक रीडलाइन कॉल अवरुद्ध हो जाएगा। कुछ उदाहरण स्क्रिप्ट जोड़ा गया। – chmullig

2

आप अपने उपप्रजाति की स्थिति पर एक मतदान कर सकते हैं और लाइनों को आउटपुट रख सकते हैं।

p = subprocess.Popen('ls;sleep 10', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

rc = p.poll() 
while rc != 0: 
    while True: 
     line = p.stdout.readline() 
     if not line: 
      break 
     print line 
    rc = p.poll() 

assert rc == 0 
1

यह निश्चित रूप से संभव है: अपने पैकेज python-gnupg वास्तव में यह करता है, को उत्पन्न करने gpg (जीएनयू गोपनीयता गार्ड) एक उपप्रजाति के तहत। सामान्य स्थिति में आपको subprocess stdout और stderr के लिए subprocess.PIPE निर्दिष्ट करने की आवश्यकता है; फिर दो अलग-अलग धागे बनाएं जो सबप्रोसेस स्टडआउट और स्टेडर को जहां चाहें पढ़ें।

python-gnupg के मामले में, जीपीजी से स्थिति संदेश पढ़े जाते हैं और gpg प्रक्रिया चल रही है (यह समाप्त होने तक प्रतीक्षा नहीं कर रही है) पर कार्य किया जाता है।

असल में, स्यूडोकोड

process = subprocess.Popen(..., stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
stderr = process.stderr 
rr = threading.Thread(target=response_reader_func, args=(process.stderr,)) 
rr.setDaemon(True) 
rr.start() 

dr = threading.Thread(target=data_reader_func, args=(process.stdout,)) 
dr.setDaemon(True) 
dr.start() 

dr.join() 
rr.join() 
process.wait() 

पाठक कार्यों को आम तौर पर जो वे क्या पढ़ रहे हैं के आधार पर सही काम एक संलग्नित क्लास के तरीके हैं (आपके मामले में, किसी तरह से प्रगति की जानकारी अद्यतन करना) है।

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