![](/img/trans.png)
[英]Python subprocess interaction, why does my process work with Popen.communicate, but not Popen.stdout.read()?
[英]Python subprocess Popen.communicate() equivalent to Popen.stdout.read()?
非常具體的問題(我希望): 以下三個代碼之間有什么區別?
(我希望它只是第一個不等待子進程完成,而第二個和第三個進行。但我需要確定這是唯一的區別......)
我也歡迎其他評論/建議(雖然我已經很清楚shell=True
危險和跨平台限制)
請注意,我已經閱讀過Python子進程交互,為什么我的進程可以使用Popen.communicate,但不能使用Popen.stdout.read()? 並且我不希望/之后需要與程序交互。
另請注意,我已經閱讀了Python Popen.communicate()內存限制的替代品? 但是我沒有真正得到它......
最后,請注意我知道當一個緩沖區使用一種方法填充一個輸出時存在死鎖的風險,但我在互聯網上尋找清晰的解釋時迷路了...
第一個代碼:
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
謝謝。
如果你查看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)
您可以看到, communicate
確實利用了對stdout
和stderr
的讀取調用,並且還調用了wait()
。 這只是一個操作順序問題。 在你的情況下,因為你對stdout和stderr使用PIPE
,它進入_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()
。
總結一下:
此外,在第2和第3個示例中,您不需要這兩個import語句:
from subprocess import communicate
from subprocess import wait
它們都是Popen
對象的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.