Quelle est la différence entre le sous-processus Popen et l'appel (comment puis-je les utiliser)?

178

Je souhaite appeler un programme externe depuis Python. J'ai utilisé les deux Popen()et call()pour le faire.

Quelle est la différence entre les deux?

Mon objectif spécifique est d'exécuter la commande suivante à partir de Python. Je ne sais pas comment fonctionnent les redirections.

./my_script.sh > output

J'ai lu la documentation et il est dit que call()c'est une fonction pratique ou une fonction de raccourci. Perdons-nous du pouvoir en utilisant call()au lieu de Popen()?

varunl
la source
Quelle partie de la documentation vous a dérouté? La définition de call()semble être très claire. Pouvez-vous fournir un devis ou un lien pour que nous sachions sur quoi nous concentrer dans une réponse?
S.Lott

Réponses:

265

Il existe deux façons de faire la redirection. Les deux s'appliquent à l'un subprocess.Popenou l' autre subprocess.call.

  1. Définissez l'argument de mot-clé shell = Trueou executable = /path/to/the/shellet spécifiez la commande telle que vous l'avez là.

  2. Puisque vous ne faites que rediriger la sortie vers un fichier, définissez l'argument mot-clé

    stdout = an_open_writeable_file_object

    où l'objet pointe vers le outputfichier.

subprocess.Popenest plus général que subprocess.call.

Popenne bloque pas, vous permettant d'interagir avec le processus pendant son exécution, ou de continuer avec d'autres choses dans votre programme Python. L'appel à Popenrenvoie un Popenobjet.

call fait bloc. Bien qu'il prenne en charge tous les mêmes arguments que le Popenconstructeur, afin que vous puissiez toujours définir la sortie du processus, les variables d'environnement, etc., votre script attend que le programme se termine et callrenvoie 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()

callest juste une fonction de commodité. Son implémentation dans CPython est dans subprocess.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, c'est une mince enveloppe autour Popen.

agf
la source
17
Fondamentalement, Popen et call sont des fonctions asynchrones et synchrones utilisées respectivement pour exécuter des commandes Linux.
user3016020
1
Quel est l'avantage d'utiliser popen? Ne serait-il pas prudent d'attendre que le programme appelé se termine en premier?
Tom
4
@Tom Souvent pas. Que faire si vous voulez lire une sortie, puis envoyer plus d'entrée au programme, lire plus de sortie qui résulte de cette entrée, répéter?
agf
@ user3016020 Je suppose que cela s'applique également aux commandes Windows? Droite?
domih
7

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

  • call bloque:

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

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