209 votes

Quelle est la différence entre subprocess Popen et call (comment puis-je les utiliser) ?

Je veux appeler un programme externe à partir de Python. J'ai utilisé à la fois Popen() y call() pour le faire.

Quelle est la différence entre les deux ?

Mon objectif spécifique est d'exécuter la commande suivante depuis Python. Je ne suis pas sûr du fonctionnement des redirections.

./my_script.sh > output

Je lis la documentation et il est dit que call() est une fonction de commodité ou une fonction de raccourci. Perdons-nous de la puissance en utilisant call() au lieu de Popen() ?

0 votes

Quelle partie de la documentation vous a dérouté ? La définition de call() semble être très clair. Pouvez-vous fournir une citation ou un lien afin que nous sachions sur quoi nous concentrer dans notre réponse ?

298voto

agf Points 45052

Il existe deux façons de procéder à la redirection. Les deux s'appliquent soit à subprocess.Popen o subprocess.call .

  1. Définir l'argument du mot-clé shell = True o executable = /path/to/the/shell et spécifier la commande comme vous l'avez fait ici.

  2. Puisque vous redirigez simplement la sortie vers un fichier, définissez l'argument du mot-clé

    stdout = an_open_writeable_file_object

    où l'objet pointe vers le output fichier.

subprocess.Popen est plus général que subprocess.call .

Popen ne bloque pas, ce qui vous permet d'interagir avec le processus pendant qu'il est en cours d'exécution, ou de poursuivre d'autres activités dans votre programme Python. L'appel à Popen renvoie un Popen objet.

call hace bloc. Bien qu'il prenne en charge tous les mêmes arguments que le Popen constructeur, de sorte que vous pouvez toujours définir la sortie du processus, les variables d'environnement, etc., votre script attend que le programme se termine, et call renvoie un code représentant l'état de sortie du processus.

returncode = call(*args, **kwargs) 

est fondamentalement la même chose que d'appeler

returncode = Popen(*args, **kwargs).wait()

call est juste une fonction de commodité. Son implémentation dans CPython est dans sous-processus.py :

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

Comme vous pouvez le voir, il s'agit d'une fine enveloppe autour de Popen .

27 votes

Fondamentalement, Popen et call sont des fonctions asynchrones et synchrones respectivement utilisées pour exécuter des commandes Linux.

1 votes

Quel est l'avantage d'utiliser le popen ? Ne serait-il pas plus sûr d'attendre que le programme appelé se termine en premier ?

4 votes

@Tom Souvent non. Et si vous voulez lire une sortie, puis envoyer d'autres entrées au programme, lire d'autres sorties résultant de ces entrées, répéter ?

44voto

Basj Points 776

L'autre réponse est très complète, mais voici une règle empirique :

  • call est bloqué :

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
  • Popen est non bloquant :

    Popen('notepad.exe')
    print('hello')  # immediately executed

4 votes

Explication agréable et facilement compréhensible. Merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X