非常に具体的な質問(私は願っています):次の3つのコードの違いは何ですか?
(最初のプロセスは子プロセスの終了を待たず、2番目と3番目のプロセスは終了することだけを期待しています。しかし、これはonly違い...)
また、他の発言/提案も歓迎します(ただし、Shell=True
危険とクロスプラットフォームの制限)
私はすでに読んでいることに注意してください Pythonサブプロセスの相互作用、なぜ私のプロセスはPopen.communicateで動作しますが、Popen.stdout.read()で動作しないのですか? 。
また、すでに読んだことに注意してください Python Popen.communicate()メモリの制限? の代替案)==しかし、私は実際にそれを取得しませんでした...
最後に、1つのメソッドを使用して1つのバッファーが1つの出力で満たされると、デッドロックのリスクがあることを認識していますが、インターネットで明確な説明を探しているときに迷子になりました...
最初のコード:
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
2番目のコード:
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
3番目のコード:
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番目の例では、次の2つのimportステートメントは必要ありません。
_from subprocess import communicate
from subprocess import wait
_
これらは両方ともPopen
オブジェクトのメソッドです。