2012-10-18 10 views
28

बहुत विशिष्ट प्रश्न (मुझे आशा है): निम्नलिखित तीन कोडों के बीच अंतर क्या हैं?पायथन subprocess Popen.communicate() Popen.stdout.read() के बराबर है?

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

मैं भी स्वागत अन्य टिप्पणी/सुझाव (हालांकि मैं पहले से ही shell=True खतरों और पार मंच सीमाओं)

नोट से अच्छी तरह परिचित है कि मैं पहले से ही Python subprocess interaction, why does my process work with Popen.communicate, but not Popen.stdout.read()? पढ़ सकते हैं और है कि मैं नहीं चाहता हूँ/बातचीत करने के लिए की जरूरत है कार्यक्रम के बाद के साथ।

भी ध्यान रखें कि मैं पहले से ही Alternatives to Python Popen.communicate() memory limitations? पढ़ा लेकिन यह है कि मैं वास्तव में यह नहीं मिला ...

अंत में, ध्यान दें कि मुझे पता है गतिरोध का खतरा है जब एक बफर एक उत्पादन से भर जाता है है कि कहीं न कहीं हूँ एक विधि का उपयोग कर, लेकिन, जबकि इंटरनेट पर स्पष्ट व्याख्या की तलाश में मैं खो गया ...

पहले कोड:

from subprocess import Popen, PIPE 

def exe_f(command='ls -l', shell=True): 
    """Function to execute a command and return stuff""" 

    process = Popen(command, shell=shell, stdout=PIPE, stderr=PIPE) 

    stdout = process.stdout.read() 
    stderr = process.stderr.read() 

    return process, stderr, stdout 

दूसरा कोड:

from subprocess import Popen, PIPE 
from subprocess import communicate 

def exe_f(command='ls -l', shell=True): 
    """Function to execute a command and return stuff""" 

    process = Popen(command, shell=shell, stdout=PIPE, stderr=PIPE) 

    (stdout, stderr) = process.communicate() 

    return process, stderr, stdout 

तीसरा कोड:

from subprocess import Popen, PIPE 
from subprocess import wait 

def exe_f(command='ls -l', shell=True): 
    """Function to execute a command and return stuff""" 

    process = Popen(command, shell=shell, stdout=PIPE, stderr=PIPE) 

    code = process.wait() 
    stdout = process.stdout.read() 
    stderr = process.stderr.read() 

    return process, stderr, stdout 

धन्यवाद।

उत्तर

37

आप subprocess.communicate() के लिए स्रोत को देखें, तो यह अंतर का एक आदर्श उदाहरण दिखाता है:

def communicate(self, input=None): 
    ... 
    # Optimization: If we are only using one pipe, or no pipe at 
    # all, using select() or threads is unnecessary. 
    if [self.stdin, self.stdout, self.stderr].count(None) >= 2: 
     stdout = None 
     stderr = None 
     if self.stdin: 
      if input: 
       self.stdin.write(input) 
      self.stdin.close() 
     elif self.stdout: 
      stdout = self.stdout.read() 
      self.stdout.close() 
     elif self.stderr: 
      stderr = self.stderr.read() 
      self.stderr.close() 
     self.wait() 
     return (stdout, stderr) 

    return self._communicate(input) 

आप देख सकते हैं कि communicatestdout और stderr को पढ़ने के कॉल का इस्तेमाल करते हैं करता है, और यह भी wait() कॉल । यह केवल संचालन के आदेश का मामला है। आपके मामले में क्योंकि आप दोनों stdout के लिए PIPE उपयोग कर रहे हैं और stderr, यह _communicate() में चला जाता है:

def _communicate(self, input): 
    stdout = None # Return 
    stderr = None # Return 

    if self.stdout: 
     stdout = [] 
     stdout_thread = threading.Thread(target=self._readerthread, 
             args=(self.stdout, stdout)) 
     stdout_thread.setDaemon(True) 
     stdout_thread.start() 
    if self.stderr: 
     stderr = [] 
     stderr_thread = threading.Thread(target=self._readerthread, 
             args=(self.stderr, stderr)) 
     stderr_thread.setDaemon(True) 
     stderr_thread.start() 

    if self.stdin: 
     if input is not None: 
      self.stdin.write(input) 
     self.stdin.close() 

    if self.stdout: 
     stdout_thread.join() 
    if self.stderr: 
     stderr_thread.join() 

    # All data exchanged. Translate lists into strings. 
    if stdout is not None: 
     stdout = stdout[0] 
    if stderr is not None: 
     stderr = stderr[0] 

    # Translate newlines, if requested. We cannot let the file 
    # object do the translation: It is based on stdio, which is 
    # impossible to combine with select (unless forcing no 
    # buffering). 
    if self.universal_newlines and hasattr(file, 'newlines'): 
     if stdout: 
      stdout = self._translate_newlines(stdout) 
     if stderr: 
      stderr = self._translate_newlines(stderr) 

    self.wait() 
    return (stdout, stderr) 

इस धागे का उपयोग करता है एक साथ कई धाराओं से पढ़ने के लिए। फिर यह अंत में wait() पर कॉल करता है।

तो यह योग करने के लिए ऊपर:

  1. यह उदाहरण एक समय में एक धारा से पढ़ता है और यह प्रक्रिया समाप्त होने की प्रतीक्षा नहीं करता है।
  2. यह उदाहरण आंतरिक धागे के माध्यम से एक ही समय में दोनों धाराओं से पढ़ता है, और प्रक्रिया को समाप्त करने के लिए प्रतीक्षा करता है।
  3. यह उदाहरण प्रक्रिया समाप्त होने की प्रतीक्षा करता है, और फिर एक समय में एक स्ट्रीम पढ़ता है। और जैसा कि आपने बताया है कि धाराओं में बहुत अधिक लिखा गया है तो डेडलॉक की संभावना है।

इसके अलावा, आप अपने 2 और 3 उदाहरण में इन दो आयात बयान की जरूरत नहीं है:

from subprocess import communicate 
from subprocess import wait 

वे Popen वस्तु के दोनों तरीके हैं।

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