Question très spécifique (j'espère): Quelles sont les différences entre les trois codes suivants?
(Je m'attends à ce que le premier n'attende pas la fin du processus enfant, tandis que le deuxième et le troisième le font. Mais je dois être sûr que c'est la différence seulement. ..)
Je me réjouis également d'autres remarques/suggestions (bien que je sois déjà bien au courant du Shell=True
dangers et limitations multiplateformes)
Notez que j'ai déjà lu Interaction du sous-processus Python, pourquoi mon processus fonctionne-t-il avec Popen.communicate, mais pas Popen.stdout.read ()? et que je ne veux/n'ai pas besoin d'interagir avec le programme après .
Notez également que j'ai déjà lu Alternatives à Python Popen.communicate ()? mais que je ne l'ai pas vraiment compris ...
Enfin, notez que je suis conscient que quelque part il y a un risque de blocage lorsqu'un tampon est rempli avec une sortie en utilisant une méthode, mais je me suis perdu en cherchant des explications claires sur Internet ...
Premier code:
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
Deuxième code:
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
Troisième code:
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
Merci.
Si vous regardez la source de subprocess.communicate()
, cela montre un exemple parfait de la différence:
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)
Vous pouvez voir que communicate
utilise les appels de lecture à stdout
et stderr
, et appelle également wait()
. C'est juste une question d'ordre des opérations. Dans votre cas, car vous utilisez PIPE
pour stdout et stderr, il va dans _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)
Cela utilise des threads pour lire à partir de plusieurs flux à la fois. Ensuite, il appelle wait()
à la fin.
Donc, pour résumer:
De plus, vous n'avez pas besoin de ces deux instructions d'importation dans vos 2e et 3e exemples:
from subprocess import communicate
from subprocess import wait
Ce sont les deux méthodes de l'objet Popen
.