प्रक्रिया चलने के दौरान लगातार सबप्रोसेस आउटपुट प्रिंट करें


204

मेरे पायथन-लिपियों से प्रोग्राम लॉन्च करने के लिए, मैं निम्नलिखित विधि का उपयोग कर रहा हूं:

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

इसलिए जब मैं एक प्रक्रिया शुरू Process.execute("mvn clean install")करता हूं, जैसे मेरा कार्यक्रम प्रक्रिया पूरी होने तक इंतजार करता है, और उसके बाद ही मुझे अपने कार्यक्रम का पूरा आउटपुट मिलता है। अगर मैं एक ऐसी प्रक्रिया चला रहा हूं जो खत्म होने में थोड़ी देर लगाती है तो यह कष्टप्रद है।

क्या मैं अपने प्रोग्राम को प्रोसेस आउटपुट लाइन को लाइन से लिखने देता हूं, प्रक्रिया के आउटपुट को मतदान से पहले समाप्त करके या किसी चीज में?

** [EDIT] क्षमा करें, मैंने इस प्रश्न को पोस्ट करने से पहले बहुत अच्छी तरह से नहीं खोजा। थ्रेडिंग वास्तव में महत्वपूर्ण है। यहां एक उदाहरण मिला जो दिखाता है कि यह कैसे करना है: ** पायथन सबप्रोसेस।एक धागे से खोलें


उपप्रकार के बजाय धागा, मुझे लगता है
चींटी

9
नहीं, आपको थ्रेड्स की आवश्यकता नहीं है। संपूर्ण पाइपिंग विचार काम करता है क्योंकि आप प्रक्रियाओं से पढ़ / लिख सकते हैं जबकि वे चल रहे हैं।
tokland

जवाबों:


266

आप उपयोग कर सकते हैं आईटीईआर : जल्द ही आदेश आउटपुट उन्हें जितनी लाइनों पर कार्रवाई करने के lines = iter(fd.readline, "")। यहाँ एक पूर्ण उदाहरण दिखा रहा है एक सामान्य उपयोग के मामले (@jfs के लिए धन्यवाद)

from __future__ import print_function # Only Python 2.x
import subprocess

def execute(cmd):
    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
    for stdout_line in iter(popen.stdout.readline, ""):
        yield stdout_line 
    popen.stdout.close()
    return_code = popen.wait()
    if return_code:
        raise subprocess.CalledProcessError(return_code, cmd)

# Example
for path in execute(["locate", "a"]):
    print(path, end="")

24
मैंने इस कोड की कोशिश की है (एक प्रोग्राम के साथ जिसे चलाने में महत्वपूर्ण समय लगता है) और इसकी पुष्टि कर सकता है कि वे लाइनों को प्राप्त करते हैं, जैसा कि वे प्राप्त करते हैं, पूरा होने के लिए प्रतीक्षा करने के बजाय। यह बेहतर उत्तर imo है।
एंड्रयू मार्टिन

11
नोट: पायथन 3 में, आप उपयोग कर सकते हैं for line in popen.stdout: print(line.decode(), end='')। पायथन 2 और 3 दोनों का समर्थन करने के लिए, बाइट्स शाब्दिक का उपयोग करें: b''अन्यथा lines_iteratorकभी पायथन 3 पर समाप्त नहीं होता है
17

3
इस दृष्टिकोण के साथ समस्या यह है कि अगर प्रक्रिया कुछ भी लिखने के लिए बिना कुछ लिए रुक जाती है तो पढ़ने के लिए अधिक इनपुट नहीं है। प्रक्रिया समाप्त हो गई है या नहीं, यह जांचने के लिए आपको लूप की आवश्यकता होगी। मैं अजगर 2.7 पर इस subprocess32 उपयोग करने की कोशिश
हर

7
यह काम करना चाहिए। इसे चमकाने के लिए, आप इसे जोड़ सकते हैं bufsize=1(यह पायथन 2 पर प्रदर्शन में सुधार कर सकता है), popen.stdoutपाइप को स्पष्ट रूप से बंद करें (कचरा संग्रह की प्रतीक्षा किए बिना) इसकी देखभाल करें, और बढ़ाएं subprocess.CalledProcessError(जैसे check_call(), check_output()क्या करें)। printबयान अजगर 2 और 3 पर अलग है: आप softspace हैक इस्तेमाल कर सकते हैं print line,(ध्यान दें: अल्पविराम) अपने कोड की तरह सभी नई-पंक्तियों को दोगुना करने से बचने के लिए करता है और गुजर universal_newlines=Trueअजगर 3 पर, bytes- के बजाय पाठ प्राप्त करने के लिए संबंधित जवाब
JFS

6
@binzhang यह एक त्रुटि नहीं है, स्टडआउट को पाइथन लिपियों पर डिफ़ॉल्ट रूप से बफर किया जाता है (कई यूनिक्स उपकरणों के लिए भी)। कोशिश करो execute(["python", "-u", "child_thread.py"])। अधिक जानकारी: stackoverflow.com/questions/14258500/…
tokland

84

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

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline()
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

3
विलय ifischer की और tokland के कोड काफी अच्छी तरह से काम करता है (मैं परिवर्तन करना पड़ा print line,करने के लिए sys.stdout.write(nextline); sys.stdout.flush()। अन्यथा, यह हर दो पंक्तियों का प्रिंट आउट होगा फिर, इस IPython नोटबुक इंटरफ़ेस का उपयोग कर रहा है, इसलिए हो सकता है कुछ और ही हो रहा था -। परवाह किए बिना, स्पष्ट रूप से बुला flush()काम करता है।
eacousineau

3
मिस्टर यू आर माई लाइफ सेवर !! वास्तव में अजीब बात है कि इस तरह की चीजें लाइब्रेरी में ही निर्मित नहीं होती हैं .. क्योंकि अगर मैं क्लियाप लिखता हूं, तो मैं सब कुछ दिखाना चाहता हूं जो तुरंत लूप में प्रसंस्करण कर रहा है .. s'rsly ..
होम्स

3
क्या इस समाधान को आउटपुट और त्रुटियों दोनों को लगातार प्रिंट करने के लिए संशोधित किया जा सकता है ? यदि मैं बदल stderr=subprocess.STDOUTजाता हूं stderr=subprocess.PIPEऔर फिर process.stderr.readline()लूप के भीतर से कॉल करता हूं, तो मैं बहुत ही गतिरोध के पीछे भागता हूं जो कि subprocessमॉड्यूल के लिए प्रलेखन में चेतावनी दी गई है ।
davidrmcharles

7
@DavidCharles मुझे लगता है कि आप जो देख रहे हैं, वह स्टैडर है stdout=subprocess.PIPE,stderr=subprocess.STDOUT, और मुझे विश्वास है (लेकिन मैंने परीक्षण नहीं किया है) कि यह स्टड को भी पकड़ता है।
एंड्रयू मार्टिन

निकास कोड की प्रतीक्षा करने के लिए धन्यवाद। यह पता नहीं था कि इसे कैसे काम करना है
विटाली इसव

69

जैसे ही इसके स्टेपआउट बफर को पायथन 3 में प्रवाहित किया जाता है, उप-उत्पादन लाइन-बाय-लाइन प्रिंट करने के लिए:

from subprocess import Popen, PIPE, CalledProcessError

with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
    for line in p.stdout:
        print(line, end='') # process line here

if p.returncode != 0:
    raise CalledProcessError(p.returncode, p.args)

सूचना: आपको ज़रूरत नहीं है p.poll()- ईओफ़ तक पहुंचने पर लूप समाप्त हो जाता है। और आपको ज़रूरत नहीं है iter(p.stdout.readline, '')- पायथन 3 में रीड-फॉरवर्ड बग तय किया गया है।

यह भी देखें, पायथन: सबप्रोसेसर.कॉम विमुद्रीकृत () से स्ट्रीमिंग इनपुट पढ़ें


3
इस समाधान ने मेरे लिए काम किया। ऊपर दिया गया स्वीकृत समाधान सिर्फ मेरे लिए रिक्त लाइनों को प्रिंट करने पर चला गया।
कोडनेम

3
मुझे तुरंत प्रिंट प्राप्त करने के लिए sys.stdout.flush () को जोड़ना पड़ा।
कोडनेम

3
@ कोडेन: आपको sys.stdout.flush()अभिभावक की आवश्यकता नहीं होनी चाहिए - यदि फाइल / पाइप पर रीडायरेक्ट नहीं किया गया है तो stdout लाइन-बफ़र्ड है और इसलिए मुद्रण lineस्वचालित रूप से बफर को फ्लश करता है। आपको sys.stdout.flush()बच्चे में भी ज़रूरत नहीं है - -uइसके बजाय कमांड-लाइन विकल्प पास करें ।
jfs

1
@ कोडनाम: यदि आप उपयोग करना चाहते हैं >तो चलाएं python -u your-script.py > some-file। सूचना: -uवह विकल्प जिसका मैंने ऊपर उल्लेख किया है (उपयोग करने की आवश्यकता नहीं है sys.stdout.flush())।
jfs

1
@mvidelgauz को कॉल करने की आवश्यकता नहीं है p.wait()- इसे withब्लॉक से बाहर निकलने पर बुलाया जाता है । का उपयोग करें p.returncode
jfs

8

जब आप सिर्फ आउटपुट प्रिंट करना चाहते हैं तो वास्तव में ऐसा करने का एक सरल तरीका है :

import subprocess
import sys

def execute(command):
    subprocess.check_call(command, stdout=sys.stdout, stderr=subprocess.STDOUT)

यहां हम केवल उप-वर्ग को अपने स्वयं के स्टडआउट की ओर इशारा कर रहे हैं, और मौजूदा सफल या अपवाद एपीआई का उपयोग कर रहे हैं।


1
पायथन 3.6 के लिए, यह समाधान @ टोकन के समाधान की तुलना में सरल और साफ है। मैंने देखा कि शेल = सही तर्क आवश्यक नहीं है।
शुभ होगा

अच्छी पकड़, अच्छा होगा। हटायाshell=True
एंड्रयू रिंग

बहुत विस्मयकारी, और छोटे कोड के साथ पूरी तरह से काम करता है। हो सकता है कि आप उपप्रोसेसर को sys.stderr पर भी पुनर्निर्देशित करें?
मनु

मनु तुम निश्चित रूप से कर सकते हो। मैं यहाँ नहीं था, क्योंकि प्रश्न में प्रयास stdout stderr को पुनर्निर्देशित कर रहा था।
एंड्रयू रिंग

क्या आप बता सकते हैं कि sys.stdout और subprocess.STDOUT में क्या अंतर है?
रॉन सेरुया

7

@tokland

अपना कोड आज़माया और इसे 3.4 के लिए ठीक कर दिया और विंडोज़ dir.cmd एक साधारण dir कमांड है, जिसे cmd-file के रूप में सहेजा गया है

import subprocess
c = "dir.cmd"

def execute(command):
    popen = subprocess.Popen(command, stdout=subprocess.PIPE,bufsize=1)
    lines_iterator = iter(popen.stdout.readline, b"")
    while popen.poll() is None:
        for line in lines_iterator:
            nline = line.rstrip()
            print(nline.decode("latin"), end = "\r\n",flush =True) # yield line

execute(c)

3
आप अपना कोड सरल कर सकते हैं । iter()और end='\r\n'अनावश्यक हैं। पाइथन डिफ़ॉल्ट रूप से सार्वभौमिक न्यूलाइन्स मोड का उपयोग करता है, किसी भी मुद्रण के दौरान '\n'अनुवाद किया जाता है '\r\n''latin'शायद एक गलत एन्कोडिंग है, आप universal_newlines=Trueपायथन 3 में टेक्स्ट आउटपुट प्राप्त करने के लिए उपयोग कर सकते हैं (लोकेल के पसंदीदा एन्कोडिंग का उपयोग करके डिकोड किया गया)। बंद न करें .poll(), बिना पढ़े डेटा को बफर किया जा सकता है। यदि पायथन लिपि एक कंसोल में चल रही है, तो इसका आउटपुट लाइन-बफ़र्ड है; आप -uविकल्प का उपयोग करके लाइन-बफ़रिंग को बाध्य कर सकते हैं - आपको flush=Trueयहां ज़रूरत नहीं है।
10

5

यदि कोई व्यक्ति दोनों से stdoutऔर stderrएक ही समय में धागे का उपयोग करके पढ़ना चाहता है , तो यह है:

import threading
import subprocess
import Queue

class AsyncLineReader(threading.Thread):
    def __init__(self, fd, outputQueue):
        threading.Thread.__init__(self)

        assert isinstance(outputQueue, Queue.Queue)
        assert callable(fd.readline)

        self.fd = fd
        self.outputQueue = outputQueue

    def run(self):
        map(self.outputQueue.put, iter(self.fd.readline, ''))

    def eof(self):
        return not self.is_alive() and self.outputQueue.empty()

    @classmethod
    def getForFd(cls, fd, start=True):
        queue = Queue.Queue()
        reader = cls(fd, queue)

        if start:
            reader.start()

        return reader, queue


process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdoutReader, stdoutQueue) = AsyncLineReader.getForFd(process.stdout)
(stderrReader, stderrQueue) = AsyncLineReader.getForFd(process.stderr)

# Keep checking queues until there is no more output.
while not stdoutReader.eof() or not stderrReader.eof():
   # Process all available lines from the stdout Queue.
   while not stdoutQueue.empty():
       line = stdoutQueue.get()
       print 'Received stdout: ' + repr(line)

       # Do stuff with stdout line.

   # Process all available lines from the stderr Queue.
   while not stderrQueue.empty():
       line = stderrQueue.get()
       print 'Received stderr: ' + repr(line)

       # Do stuff with stderr line.

   # Sleep for a short time to avoid excessive CPU use while waiting for data.
   sleep(0.05)

print "Waiting for async readers to finish..."
stdoutReader.join()
stderrReader.join()

# Close subprocess' file descriptors.
process.stdout.close()
process.stderr.close()

print "Waiting for process to exit..."
returnCode = process.wait()

if returnCode != 0:
   raise subprocess.CalledProcessError(returnCode, command)

मैं बस इसे साझा करना चाहता था, जैसा कि मैंने इस सवाल पर कुछ ऐसा ही करने की कोशिश की, लेकिन जवाबों में से किसी ने भी मेरी समस्या हल नहीं की। उम्मीद है कि यह किसी की मदद करता है!

ध्यान दें कि मेरे उपयोग के मामले में, एक बाहरी प्रक्रिया उस प्रक्रिया को मार देती है जो हम करते हैं Popen()


1
मुझे python2 के लिए लगभग कुछ इसी तरह का उपयोग करना है। जबकि python2 में ऐसा कुछ प्रदान किया जाना चाहिए था, लेकिन ऐसा कुछ नहीं है, यह बिल्कुल ठीक है।
स्टुअर्ट एक्सॉन

3

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

लक्ष्य स्क्रिप्ट में प्रत्येक स्टडआउट लिखने के बाद निम्नलिखित जोड़कर इसे ठीक किया जा सकता है:

sys.stdout.flush()

1
लेकिन पायथन को पायथन के उपप्रकार के रूप में चलाना पहले स्थान पर पागल है। आपकी स्क्रिप्ट बस importदूसरी स्क्रिप्ट होनी चाहिए ; में देखो multiprocessingया threadingयदि आप समानांतर निष्पादन की आवश्यकता है।
ट्रिपल

3
@triplee ऐसे कई परिदृश्य हैं जिनमें पायथन को पायथन के उपप्रकार के रूप में चलाना उचित है। मेरे पास कई पायथॉन बैच स्क्रिप्ट हैं जिन्हें मैं क्रमिक रूप से, दैनिक रूप से चलाना चाहता हूं। ये एक मास्टर पायथन स्क्रिप्ट द्वारा ऑर्केस्ट्रेट किया जा सकता है जो निष्पादन शुरू करता है, और मुझे ईमेल करता है कि क्या चाइल्ड स्क्रिप्ट विफल हो जाती है। प्रत्येक स्क्रिप्ट को दूसरे से सैंडबॉक्स किया जाता है - कोई नामकरण संघर्ष नहीं। मैं समानांतर नहीं कर रहा हूँ इसलिए बहुप्रचारित और सूत्रण प्रासंगिक नहीं हैं।
user1379351

तुम भी एक अलग अजगर अजगर का उपयोग कर शुरू कर सकते हैं एक अलग अजगर निष्पादन योग्य है कि मुख्य अजगर कार्यक्रम जैसे,subprocess.run("/path/to/python/executable", "pythonProgramToRun.py")
Kyle Bridenstine

3

पायथन में = = 3.5 subprocess.runमेरे लिए काम करता है:

import subprocess

cmd = 'echo foo; sleep 1; echo foo; sleep 2; echo foo'
subprocess.run(cmd, shell=True)

(निष्पादन के दौरान आउटपुट प्राप्त करना भी बिना काम करता है shell=True) https://docs.python.org/3/library/subprocess.html#subprocess.run


2
यह "निष्पादन के दौरान" नहीं है। subprocess.run()कॉल केवल लौटाता है जब उपप्रक्रिया समाप्त चल रहा है।
ट्रिपलआई

1
क्या आप बता सकते हैं कि यह "निष्पादन के दौरान" कैसे नहीं है? कुछ ऐसा >>> import subprocess; subprocess.run('top')भी लगता है कि "निष्पादन के दौरान" (और शीर्ष कभी खत्म नहीं होता)। शायद मैं कुछ सूक्ष्म अंतर समझ नहीं रहा हूँ?
user7017793

यदि आप आउटपुट को वापस Python जैसे उदाहरण के लिए पुनर्निर्देशित करते हैं stdout=subprocess.PIPEतो आप केवल इसे topखत्म होने के बाद ही पढ़ सकते हैं । आपका पायथन कार्यक्रम उपप्रकार के निष्पादन के दौरान अवरुद्ध है।
त्रिकोणीय

1
सही है, यह समझ में आता है। runपद्धति अभी भी काम करता है अगर आप केवल में रुचि रखते हैं को देखने के उत्पादन के रूप में यह जेनरेट होता है। यदि आप अजगर में आउटपुट के साथ कुछ करना चाहते हैं तो अतुल्यकालिक रूप से आप सही हैं कि यह काम नहीं करता है।
user7017793

3

मूल प्रश्न का उत्तर देने के लिए, सबसे अच्छा तरीका यह है कि IMO stdoutसीधे आपके प्रोग्राम के लिए उपप्रकार को पुनर्निर्देशित कर रहा है stdout(वैकल्पिक stderrरूप से, जैसा कि नीचे उदाहरण के लिए किया जा सकता है )

p = Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
p.communicate()

3
के लिए कुछ भी निर्दिष्ट नहीं है stdoutऔर stderrकम कोड के साथ एक ही काम करता है। हालांकि मुझे लगता है स्पष्ट है
ट्रिपलआई

1

यह PoC लगातार एक प्रक्रिया से आउटपुट को पढ़ता है और जरूरत पड़ने पर एक्सेस किया जा सकता है। केवल अंतिम परिणाम रखा जाता है, अन्य सभी आउटपुट को छोड़ दिया जाता है, इसलिए PIPE को मेमोरी से बाहर निकलने से रोकता है:

import subprocess
import time
import threading
import Queue


class FlushPipe(object):
    def __init__(self):
        self.command = ['python', './print_date.py']
        self.process = None
        self.process_output = Queue.LifoQueue(0)
        self.capture_output = threading.Thread(target=self.output_reader)

    def output_reader(self):
        for line in iter(self.process.stdout.readline, b''):
            self.process_output.put_nowait(line)

    def start_process(self):
        self.process = subprocess.Popen(self.command,
                                        stdout=subprocess.PIPE)
        self.capture_output.start()

    def get_output_for_processing(self):
        line = self.process_output.get()
        print ">>>" + line


if __name__ == "__main__":
    flush_pipe = FlushPipe()
    flush_pipe.start_process()

    now = time.time()
    while time.time() - now < 10:
        flush_pipe.get_output_for_processing()
        time.sleep(2.5)

    flush_pipe.capture_output.join(timeout=0.001)
    flush_pipe.process.kill()

print_date.py

#!/usr/bin/env python
import time

if __name__ == "__main__":
    while True:
        print str(time.time())
        time.sleep(0.01)

आउटपुट: आप स्पष्ट रूप से देख सकते हैं कि केवल 2.5 2.5 के अंतराल के बीच में से कुछ भी नहीं है।

>>>1520535158.51
>>>1520535161.01
>>>1520535163.51
>>>1520535166.01

0

यह कम से कम Python3.4 में काम करता है

import subprocess

process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE)
for line in process.stdout:
    print(line.decode().strip())

1
यह समस्या है कि यह प्रक्रिया समाप्त होने तक लूप में ब्लॉक हो जाती है।
ट्रिपलआई

0

यहाँ किसी भी उत्तर ने मेरी सभी जरूरतों को पूरा नहीं किया।

  1. स्टडआउट के लिए कोई सूत्र (कोई कतार, आदि, या तो)
  2. गैर-अवरोधक के रूप में मुझे अन्य चीजों के लिए जाँच करने की आवश्यकता है
  3. PIPE का उपयोग करें क्योंकि मुझे कई चीजें करने की ज़रूरत थी, उदाहरण के लिए आउटपुट, स्ट्रीम फ़ाइल में लिखें और आउटपुट की एक स्ट्रिंग कॉपी लौटाएं।

थोड़ी सी पृष्ठभूमि: मैं थ्रेड्स के एक पूल का प्रबंधन करने के लिए एक थ्रेडपूल एक्ज़ीक्यूटर का उपयोग कर रहा हूं, प्रत्येक एक सबप्रोसेस को लॉन्च कर रहा है और उन्हें कंसीडर चला रहा है। (Python2.7 में, लेकिन इसे नए 3.x में भी काम करना चाहिए)। मैं केवल उत्पादन के लिए थ्रेड्स का उपयोग नहीं करना चाहता क्योंकि मैं अन्य चीजों के लिए जितना संभव हो उतना उपलब्ध होना चाहता हूं (20 प्रक्रियाओं का एक पूल सिर्फ चलाने के लिए 40 थ्रेड्स का उपयोग कर रहा होगा; प्रक्रिया के धागे के लिए 1 और स्टडआउट के लिए 1 ... और अधिक अगर तुम stderr मुझे लगता है चाहते हैं)

मैं बहुत सारे अपवाद वापस ले रहा हूं और इस तरह यहां यह कोड पर आधारित है जो उत्पादन में काम करता है। उम्मीद है कि मैंने इसे कॉपी और पेस्ट में बर्बाद नहीं किया। इसके अलावा, प्रतिक्रिया बहुत बहुत स्वागत है!

import time
import fcntl
import subprocess
import time

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

# Make stdout non-blocking when using read/readline
proc_stdout = proc.stdout
fl = fcntl.fcntl(proc_stdout, fcntl.F_GETFL)
fcntl.fcntl(proc_stdout, fcntl.F_SETFL, fl | os.O_NONBLOCK)

def handle_stdout(proc_stream, my_buffer, echo_streams=True, log_file=None):
    """A little inline function to handle the stdout business. """
    # fcntl makes readline non-blocking so it raises an IOError when empty
    try:
        for s in iter(proc_stream.readline, ''):   # replace '' with b'' for Python 3
            my_buffer.append(s)

            if echo_streams:
                sys.stdout.write(s)

            if log_file:
                log_file.write(s)
    except IOError:
        pass

# The main loop while subprocess is running
stdout_parts = []
while proc.poll() is None:
    handle_stdout(proc_stdout, stdout_parts)

    # ...Check for other things here...
    # For example, check a multiprocessor.Value('b') to proc.kill()

    time.sleep(0.01)

# Not sure if this is needed, but run it again just to be sure we got it all?
handle_stdout(proc_stdout, stdout_parts)

stdout_str = "".join(stdout_parts)  # Just to demo

मुझे यकीन है कि यहां ओवरहेड जोड़ा जा रहा है लेकिन यह मेरे मामले में चिंता का विषय नहीं है। कार्यात्मक रूप से यह वही करता है जो मुझे चाहिए। केवल एक चीज जो मैंने हल नहीं की है वह यह है कि यह लॉग संदेशों के लिए पूरी तरह से काम करता है लेकिन मुझे printबाद में और बाद में कुछ संदेश दिखाई देते हैं।


-2

पायथन 3.6 में मैंने इसका इस्तेमाल किया:

import subprocess

cmd = "command"
output = subprocess.call(cmd, shell=True)
print(process)

1
यह इस विशेष प्रश्न का उत्तर नहीं है। इसके उत्पादन को प्राप्त करने से पहले उपप्रकार के समाप्त होने की प्रतीक्षा विशेष रूप से और ठीक है कि ओपी बचने की कोशिश कर रहा है। पुरानी विरासत समारोह subprocess.call()में कुछ मौसा होते हैं जो नए कार्यों द्वारा तय किए जाते हैं; पायथन 3.6 में आप आम तौर पर इसके लिए उपयोग करेंगे subprocess.run(); सुविधा के लिए, पुराना आवरण फ़ंक्शन subprocess.check_output()अभी भी उपलब्ध है - यह प्रक्रिया से वास्तविक आउटपुट देता है (यह कोड केवल निकास कोड लौटाएगा, लेकिन फिर भी इसके बजाय अपरिभाषित कुछ प्रिंट करें)।
त्रिपली २५'१
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.