56 Question: Appeler une commande externe en Python

question créée à Wed, Apr 24, 2019 12:00 AM

Comment appeler une commande externe (comme si je l'avais saisie à l'invite de commande Unix ou Windows) à partir d'un script Python?

    
4297
30 réponses                              30                         

Consultez le module de sous-processus dans la bibliothèque standard:

 
import subprocess
subprocess.run(["ls", "-l"])

L'avantage du sous-processus par rapport au système est qu'il est plus flexible (vous pouvez obtenir le stdout, stderr, le code "réel", une meilleure gestion des erreurs, etc ...).

La documentation officielle recommande le sous-processus . > module sur l'alternative os.system ():

  

Le module sous-processus fournit des fonctionnalités plus puissantes pour générer de nouveaux processus et récupérer leurs résultats. utiliser ce module est préférable à cette fonction [ os.system() ].

Le " Remplacement de fonctions antérieures par Le module de sous-processus "de la documentation sous-processus peut contenir des recettes utiles.

Les anciennes versions de Python utilisent l'appel:

 
import subprocess
subprocess.call(["ls", "-l"])
    
4140
2019-04-01 22: 39: 54Z
  1. Y a-t-il un moyen d'utiliser la substitution de variable? J'ai essayé de faire echo $PATH en utilisant call(["echo", "$PATH"]), mais cela renvoyait simplement la chaîne littérale $PATH au lieu de faire une substitution. Je sais que je pourrais obtenir la variable d’environnement PATH, mais je me demande s’il existe un moyen simple de faire en sorte que la commande se comporte exactement comme si je l’avais exécutée dans bash.
    2015-09-01 23: 17: 07Z
  2. @ KevinWheeler Vous devrez utiliser shell=True pour que cela fonctionne.
    2015-09-02 20: 38: 24Z
  3. @ KevinWheeler Vous ne devez PAS utiliser shell=True, à cet effet, Python est livré avec os.path.expandvars . Dans votre cas, vous pouvez écrire: os.path.expandvars("$PATH"). @SethMMorton s'il vous plaît reconsidérer votre commentaire - > Pourquoi ne pas utiliser shell = True
    2015-11-11 20: 24: 27Z
  4. Pour simplifier au moins conceptuellement: \n call ("ls -l" .split ())
    2018-06-16 17: 15: 48Z
  5. vous avez oublié de dire qu'il a besoin de python 3.5 au moins. Cela ne fonctionne pas sur python 3.4.3 par exemple, qui est la valeur par défaut pour Ubuntu 14.04 LTS
    2019-02-02 22: 50: 04Z

Voici un résumé des méthodes permettant d’appeler des programmes externes, ainsi que des avantages et inconvénients de chacun:

  1. os.system("some_command with args") transmet la commande et les arguments au shell de votre système. C'est bien parce que vous pouvez réellement exécuter plusieurs commandes à la fois de cette manière et configurer des canaux et une redirection entrée /sortie. Par exemple:

     
    os.system("some_command < input_file | another_command > output_file")  
    

    Cependant, bien que cela soit pratique, vous devez gérer manuellement l'échappement de caractères shell tels que des espaces, etc. Cela vous permet également d'exécuter des commandes qui sont simplement des commandes shell et non des programmes externes. Voir la documentation .

  2. stream = os.popen("some_command with args") wJe ferai la même chose que os.system sauf qu’il vous donnera un objet de type fichier que vous pourrez utiliser pour accéder aux entrées /sorties standard de ce processus. Il existe 3 autres variantes de popen qui traitent toutes légèrement les entrées /sorties. Si vous transmettez tout en chaîne, votre commande est transmise au shell; si vous les transmettez sous forme de liste, vous n'avez pas à vous soucier d'échapper à quoi que ce soit. Voir la documentation .

  3. La classe Popen du module subprocess. Ceci est destiné à remplacer os.popen mais présente l'inconvénient d'être un peu plus compliqué en raison de son exhaustivité. Par exemple, vous diriez:

     
    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
    

    au lieu de:

     
    print os.popen("echo Hello World").read()
    

    mais il est bon d’avoir toutes les options dans une classe unifiée au lieu de 4 fonctions popen différentes. Voir la documentation .

  4. La fonction call du module subprocess. Cela ressemble fondamentalement à la classe Popen et prend tous les mêmes arguments, mais attend simplement que la commande se termine et vous donne le code de retour. Par exemple:

     
    return_code = subprocess.call("echo Hello World", shell=True)  
    

    Voir la documentation .

  5. Si vous utilisez Python 3.5 ou une version ultérieure, vous pouvez utiliser le nouveau subprocess.run , qui ressemble beaucoup à ce qui précède, mais est encore plus flexible et renvoie un CompletedProcess après la fin de l'exécution de la commande.

  6. Le module os possède également toutes les fonctions fork /exec /spawn que vous auriez dans un programme C, mais je ne recommande pas de les utiliser directement.

Le module subprocess devrait probablement être ce que vous utilisez.

Enfin, sachez que pour toutes les méthodes dans lesquelles vous passez la commande finale à exécuter par le shell sous forme de chaîne, vous êtes responsable de son échappement. Il y a de graves conséquences pour la sécurité si une partie de la chaîne que vous transmettez ne peut être entièrement approuvée. Par exemple, si un utilisateur entre une partie ou n’importe quelle partie de la chaîne. Si vous n'êtes pas sûr, utilisez uniquement ces méthodes avec des constantes. Pour vous donner une idée des implications, considérons ce code:

 
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

et imaginez que l'utilisateur saisisse quelque chose "ma mère ne m'a pas aimé & & rm -rf /" qui pourrait effacer tout le système de fichiers.

    
2782
2019-04-28 10: 57: 02Z
  1. 2015-05-26 21: 16: 27Z
  2. Si vous utilisez Python 3.5+, utilisez subprocess.run(). docs.python.org/3.5/library/subprocess.html#subprocess. exécuter
    2015-10-07 16: 37: 18Z
  3. Ce qu'il faut généralement savoir, c'est comment utiliser les commandes STDOUT et STDERR du processus enfant, car si elles sont ignorées, dans des conditions (assez courantes), finalement process émettra un appel système à écrire sur STDOUT (STDERR aussi?) qui dépasserait la mémoire tampon de sortie fournie au processus par le système d’exploitation. Ce dernier bloquera celui-ci jusqu’à ce qu’un processus lise à partir de cette mémoire tampon. Ainsi, avec les méthodes actuellement recommandées, subprocess.run(..), que fait exactement "Cela ne capture pas stdout ou stderr par défaut." implique-t-il? Qu'en est-il de subprocess.check_output(..) et de STDERR?
    2016-06-01 10: 44: 53Z
  4. @ Pitto oui, mais ce n'est pas ce qui est exécuté par l'exemple. Notez le echo devant la chaîne passée to Popen? Donc, la commande complète sera echo my mama didnt love me && rm -rf /.
    2018-09-10 16: 38: 25Z
  5. C'est sans doute le mauvais sens. La plupart des gens n’ont besoin que de subprocess.run() ou de ses frères et soeurs plus âgés, subprocess.check_call() et al. Pour les cas où cela ne suffit pas, voir subprocess.Popen(). os.popen() ne devrait peut-être pas être mentionné du tout, ou même après "pirater votre propre code fork /exec /spawn".
    2018-12-03 06: 00: 46Z

J'utilise généralement:

 
import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

Vous êtes libre de faire ce que vous voulez avec les données stdout dans le tuyau. En fait, vous pouvez simplement omettre ces paramètres (stdout= et stderr=) et ils se comporteront comme os.system().

    
306
2016-12-10 13: 22: 55Z
  1. .readlines() lit toutes les lignes en même temps, c’est-à-dire qu’il se bloque jusqu’à ce que le sous-processus se ferme (ferme sa fin du tuyau). Pour lire en temps réel (s’il n’ya pas de problème de mise en mémoire tampon), vous pouvez: for line in iter(p.stdout.readline, ''): print line,
    2012-11-16 14: 12: 18Z
  2. Pouvez-vous préciser ce que vous entendez par "s'il n'y a pas de problèmes de mise en mémoire tampon"? Si le processus bloque définitivement, l'appel du sous-processus est également bloqué. La même chose pourrait arriver avec mon exemple original. Que pourrait-il arriver en ce qui concerne la mise en tampon?
    2012-11-17 13: 25: 15Z
  3. le processus enfant peut utiliser la mise en mémoire tampon de blocs en mode non interactif au lieu de la mise en mémoire tampon de sorte que p.stdout.readline() (remarque: no s à la fin) ne verra aucune donnée. jusqu'à ce que l'enfant remplisse son tampon. Si l'enfant ne produit pas beaucoup de données, la sortie ne sera pas en temps réel. Voir la deuxième raison dans Q: Pourquoi ne pas utiliser simplement un tube (popen ())? . Certaines solutions de contournement sont fournies dans cette réponse (pexpect, pty, stdbuf)
    2012-11-17 13: 51: 25Z
  4. le problème de mise en mémoire tampon n'a d'importance que si vous souhaitez une sortie en temps réel et ne s'applique pas à votre code qui n'imprime rien tant que tout les données sont reçues
    2012-11-17 13: 53: 26Z
  5. Cette réponse était correcte pour son époque, mais nous ne devrions plus recommander Popen pour des tâches simples. Cela spécifie également inutilement shell=True. Essayez l’une des subprocess.run() réponses.
    2018-12-03 05: 39: 55Z

Quelques astuces sur la séparation du processus enfant du processus appelant (démarrage du processus enfant en arrière-plan).

Supposons que vous souhaitiez lancer une longue tâche à partir d'un script CGI, c'est-à-dire que le processus enfant doit vivre plus longtemps que le processus d'exécution du script CGI.

L'exemple classique tiré de la documentation du module de sous-processus est le suivant:

 
import subprocess
import sys

# some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess

# some more code here

L’idée ici est que vous ne voulez pas attendre dans la ligne 'appelez le sous-processus' que le longtask.py soit terminé. Mais il n’est pas clair ce qui se passe après la ligne "un peu plus de code ici" de l'exemple.

Ma plate-forme cible était FreeBSD, mais le développement se faisait sous Windows. J'ai donc d'abord rencontré le problème sous Windows.

Sous Windows (Win XP), le processus parent ne sera pas terminé tant que le fichier longtask.py n’aura pas terminé son travail. Ce n'est pas ce que vous voulez dans CGI-script. Le problème n’est pas spécifique à Python, dans la communauté PHP, les problèmes sont les mêmes.

La solution consiste à passer DETACHED_PROCESS Indicateur de création de processus sur la fonction CreateProcess sous-jacente dans Win API. Si vous avez installé pywin32, vous pouvez importer l’indicateur à partir du module win32process, sinon vous devez le définir vous-même:

 
DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/* UPD 2015.10.27 @erDans un commentaire, notez que l'indicateur sémantiquement correct est CREATE_NEW_CONSOLE (0x00000010) * /

Sous freebsd, nous avons un autre problème: lorsque le processus parent est terminé, il termine également les processus enfants. Et ce n’est pas ce que vous voulez dans CGI-script non plus. Certaines expériences ont montré que le problème semblait être de partager sys.stdout. Et la solution de travail était la suivante:

 
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

Je n'ai pas vérifié le code sur d'autres plates-formes et je ne connais pas les raisons du comportement de FreeBSD. Si quelqu'un le sait, partagez vos idées, s'il vous plaît. Googler lors du démarrage de processus en arrière-plan en Python n’éclaire pas encore.

    
196
2017-07-27 21: 35: 57Z
  1. J'ai remarqué une "bizarrerie" possible avec le développement d'applications py2exe dans pydev + eclipse. J'ai pu constater que le script principal n'était pas détaché car la fenêtre de sortie de Eclipse ne se terminait pas. même si le script s'exécute complètement, il attend toujours les retours. mais, lorsque j'ai essayé de compiler un exécutable py2exe, le comportement attendu se produit (exécute les processus en mode détaché, puis quitte). Je ne suis pas sûr, mais le nom de l'exécutable ne figure plus dans la liste des processus. cela fonctionne pour toutes les approches (os.system ("start *"), os.spawnl avec os.P_DETACH, sous-documents, etc.)
    2010-04-09 08: 09: 26Z
  2. vous aurez peut-être également besoin de l'indicateur CREATE_NEW_PROCESS_GROUP. Voir Popen en attente d'un processus enfant, même lorsque l'enfant immédiat s'est terminé
    .
    2012-11-16 14: 16: 42Z
  3. Ce qui suit est incorrect: "[o] n windows (win xp), le processus parent ne s'achèvera pas tant que longtask.py n'aura pas terminé son travail". Le parent va quitter normalement, mais la fenêtre de la console (instance conhost.exe) ne se ferme que lorsque le dernier processus attaché est terminé, et l'enfant a peut-être hérité de la console du parent. Définir DETACHED_PROCESS dans creationflags évite cela en empêchant l'enfant d'hériter ou de créer une console. Si vous souhaitez plutôt une nouvelle console, utilisez CREATE_NEW_CONSOLE (0x00000010).
    2015-10-27 00: 27: 30Z
  4. Je ne voulais pas dire que l'exécution en tant que processus détaché est incorrecte. Cela dit, vous devrez peut-être définir les descripteurs standard sur les fichiers, les canaux ou os.devnull, car certains programmes de la console se fermeront avec une erreur. Créez une nouvelle console lorsque vous souhaitez que le processus enfant interagisse avec l'utilisateur simultanément avec le processus parent. Il serait déroutant d'essayer de faire les deux dans une seule fenêtre.
    2015-10-27 17: 37: 15Z
  5. n’existe-t-il pas un moyen indépendant du système d’exploitation d’exécuter le processus en arrière-plan?
    2019-02-24 19: 05: 29Z

Je recommanderais d'utiliser le module de sous-processus au lieu de os.system, car le shell vous échappe et est donc beaucoup plus sûr: http://docs.python.org/library/subprocess.html

 
subprocess.call(['ping', 'localhost'])
    
120
2014-04-04 19: 46: 08Z
  1. Si vous souhaitez créer une liste à partir d'une commande avec les paramètres , liste pouvant être utilisée avec subprocess lorsque shell=False, utilisez shlex.split. pour un moyen facile de faire cela docs.python.org/2/library /shlex.html#shlex.split (c'est la méthode recommandée selon la documentation docs.python.org/2/library/subprocess.html#popen-constructor )
    2018-09-20 18: 07: 21Z
  2. Ceci est incorrect: " c’est le shell échapC’est pour vous et il est donc beaucoup plus sûr ". Le sous-processus ne permet pas d’échapper au shell, le sous-processus ne transmet pas votre commande à travers le shell, il n’est donc pas nécessaire d’écraser le shell.
    2018-12-04 08: 36: 35Z
 
import os
cmd = 'ls -al'
os.system(cmd)

Si vous souhaitez renvoyer les résultats de la commande, vous pouvez utiliser os.popen . Cependant, cette option est déconseillée depuis la version 2.6 au profit du module de sous-processus , quelles autres réponses ont bien couvert.

    
119
2016-01-26 16: 53: 05Z
  1. popen obsolète au profit du sous-processus .
    2014-08-08 00: 22: 35Z
  2. Vous pouvez également enregistrer votre résultat avec l'appel os.system, car il fonctionne comme le shell UNIX lui-même, comme par exemple os.system ('ls -l > test2.txt ')
    2017-11-07 23: 19: 20Z
 
import os
os.system("your command")

Notez que ceci est dangereux car la commande n'est pas nettoyée. Je vous laisse le soin de rechercher sur Google la documentation pertinente sur les modules «os» et «sys». Il y a un tas de fonctions (exec * et spawn *) qui feront des choses similaires.

    
115
2018-06-03 17: 10: 00Z
  1. Qu'entendez-vous par "la commande n'est pas nettoyée" ?
    2018-06-03 17: 10: 31Z
  2. Je ne sais pas ce que je voulais dire il y a près de dix ans (vérifiez la date!), mais si je devais deviner, ce serait qu'aucune validation n'avait été effectuée.
    2018-06-06 16: 01: 34Z
  3. Cela devrait maintenant indiquer subprocess comme une solution légèrement plus polyvalente et portable. L'exécution de commandes externes est bien sûr intrinsèquement imputable (vous devez vous assurer que la commande est disponible sur toutes les architectures que vous devez prendre en charge) et le fait de saisir une entrée utilisateur en tant que commande externe est intrinsèquement dangereux.
    2018-12-03 05: 11: 39Z
  4. Notez l'horodatage de ce type: la réponse "correcte" contient 40x le nombre de votes et correspond à la réponse n ° 1.
    2018-12-03 18: 41: 52Z

Il existe de nombreuses bibliothèques différentes qui vous permettent d’appeler des commandes externes avec Python. Pour chaque bibliothèque, j'ai donné une description et un exemple d'appel d'une commande externe. La commande que j'ai utilisée comme exemple est ls -l (liste de tous les fichiers). Si vous souhaitez en savoir plus sur l’une des bibliothèques que j’ai énumérées et reliée à la documentation correspondante,

.
  

Sources:

  
    
      

Ce sont toutes les bibliothèques:

    
  

Espérons que cela vous aidera à prendre une décision sur la bibliothèque à utiliser:)

  

sous-processus

Le sous-processus vous permet d'appeler des commandes externes et de les connecter à leurs canaux d'entrée /sortie /d'erreur (stdin, stdout et stderr). Le sous-processus est le choix par défaut pour l'exécution des commandes, mais parfois d'autres modules sont meilleurs.

 
subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command
  

os

os est utilisé pour "la fonctionnalité dépendant du système d'exploitation". Il peut également être utilisé pour appeler des commandes externes avec os.system et os.popen (Remarque: il existe également un sous-processus.popen). os exécutera toujours le shell et constitue une alternative simple pour les personnes qui n’ont pas besoin de, ou ne savent pas utiliser subprocess.run.

 
os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output
  

sh

sh est une interface de sous-processus qui vous permet d’appeler des programmes comme s’ils étaient des fonctions. Ceci est utile si vous souhaitez exécuter une commande plusieurs fois.

 
sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function
  

Plumbum

plumbum est une bibliothèque pour les programmes Python "de type script". Vous pouvez appeler des programmes comme des fonctions comme dans sh. Plumbum est utile si vous souhaitez exécuter un pipeline sans le shell.

 
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
  

pexpect

pexpect vous permet de créer des applications enfants, de les contrôler et de rechercher des modèles dans leur sortie. C'est une meilleure alternative au sous-processus pour les commandes qui attendent un tty sous Unix.

 
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
  

tissu

fabric est une bibliothèque Python 2.5 et 2.7. Il vous permet d'exécuter des commandes shell locales et distantes. Fabric est une alternative simple pour exécuter des commandes dans un shell sécurisé (SSH)

 
fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output
  

envoyé

envoy est appelé "sous-processus pour les humains". Il est utilisé comme un wrapper de commodité autour du module subprocess.

 
r = envoy.run("ls -l") # Run command
r.std_out # get output
  

commandes

commands contient des fonctions d'encapsulation pour os.popen, mais il a été supprimé de Python 3 car subprocess constitue une meilleure alternative.

La modification est basée sur le commentaire de J.F. Sebastian.

    
72
2017-05-28 23: 14: 34Z

J'utilise toujours fabric pour des choses comme:

 
from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

Mais cela semble être un bon outil: sh (interface de sous-processus Python) .

Regardez un exemple:

 
from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
    
64
2013-07-23 18: 28: 23Z

Vérifiez également la bibliothèque Python "pexpect".

Il permet le contrôle interactif de programmes /commandes externes, même ssh, ftp, telnet, etc. Vous pouvez simplement taper quelque chose comme:

 
child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password')
    
63
2017-05-28 23: 02: 27Z

Si vous avez besoin du résultat de la commande que vous appelez, vous pouvez alors utiliser subprocess.check_output (Python 2.7+).

 
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

Notez également le paramètre shell .

  

Si shell est True, la commande spécifiée sera exécutée viaLa coquille. Cela peut être utile si vous utilisez principalement Python pour le flux de contrôle amélioré proposé par la plupart des interpréteurs de commandes système et que vous souhaitez tout de même accéder facilement à d'autres fonctionnalités du shell, telles que les tubes de commande, les caractères génériques, l'extension des variables d'environnement et l'extension de ~ vers le domicile de l'utilisateur. annuaire. Cependant, notez que Python lui-même offre des implémentations de nombreuses fonctionnalités similaires à celles du shell (en particulier glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser() et shutil).

    
59
2018-06-03 20: 18: 34Z
  1. Notez que check_output requiert une liste plutôt qu'une chaîne. Si vous ne comptez pas sur les espaces entre guillemets pour rendre votre appel valide, le moyen le plus simple et le plus lisible de le faire est subprocess.check_output("ls -l /dev/null".split()).
    2018-01-30 18: 18: 54Z

Avec la bibliothèque standard

Le Utilisez le module de sous-processus (Python 3):

 
import subprocess
subprocess.run(['ls', '-l'])

C’est la méthode standard recommandée. Cependant, des tâches plus complexes (pipes, sortie, entrée, etc.) peuvent être fastidieuses à construire et à écrire.

Note sur la version Python: Si vous utilisez toujours Python 2, subprocess.call fonctionne de manière similaire.

Conseils: shlex.split peut vous aider. vous devez analyser la commande pour run, call et autres fonctions subprocess au cas où vous ne voudriez pas (ou que vous ne puissiez pas!) les fournir sous forme de listes:

 
import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

Avec dépendances externes

Si les dépendances externes ne vous dérangent pas, utilisez plumbum :

 
from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())

C’est le meilleur wrapper subprocess. Il est multi-plateforme, c’est-à-dire qu’il fonctionne à la fois sous Windows et sous Unix. Installez avant pip install plumbum.

Une autre bibliothèque populaire est sh :

 
from sh import ifconfig
print(ifconfig('wlan0'))

Cependant, sh a cessé de prendre en charge Windows. Ce n'est donc pas aussi génial qu'avant. Installez avant pip install sh.

    
56
2018-09-19 13: 55: 27Z

C’est ainsi que j’exécute mes commandes. Ce code contient tout ce dont vous avez besoin

 
from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()
    
49
2012-10-28 05: 44: 05Z
  1. Passer des commandes sous forme de chaînes est généralement une mauvaise idée
    2013-07-23 18: 29: 11Z
  2. Je pense que cela est acceptable pour les commandes codées en dur, si cela améliore la lisibilité.
    2014-04-02 13: 07: 44Z

Mise à jour:

subprocess.run est l'approche recommandée à partir de Python 3.5 si votre code n'a pas besoin de maintenir la compatibilité avec les versions antérieures de Python. Il est plus cohérent et offre une facilité d'utilisation similaire à celle d'Envoy. (La tuyauterie n’est cependant pas aussi simple. Voir cette question pour savoir comment .)

Voici quelques exemples tirés de les documents .

Exécuter un processus:

 
>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

Relancer en cas d'échec de l'exécution:

 
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Sortie de capture:

 
>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

Réponse originale:

Je vous recommande d'essayer Envoy . C'est un wrapper pour les sous-processus, qui à leur tour vise à remplacer les anciens modules et fonctions. Envoy est un sous-processus destiné aux humains.

Exemple d'utilisation de le fichier Lisez-moi :

 
>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''

Diffusez aussi des trucs:

 
>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[<Response 'uptime'>]
    
45
2017-05-23 12: 26: 36Z

Sans la sortie du résultat:

 
import os
os.system("your command here")

Avec sortie du résultat:

 
import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
    
37
2017-05-28 22: 59: 14Z
  1. commands n'est plus disponible dans Python 3. Vous devriez préférer subprocess à os.system()
    2018-12-03 05: 33: 09Z

https://docs.python.org/2/library/subprocess.html

... ou pour une commande très simple:

 
import os
os.system('cat testfile')
    
32
2014-11-02 04: 00: 55Z

Il existe également des Plumbum

.  
>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns
    
30
2014-10-10 17: 41: 13Z

os.system est OK, mais un peu daté. Ce n'est pas très sécurisé non plus. Au lieu de cela, essayez subprocess. subprocess n'appelle pas sh directement et est donc plus sécurisé que os.system.

Obtenir plus d'informations ici .

    
29
2016-12-10 13: 25: 05Z
  1. Bien que je souscrive à la recommandation générale, subprocess ne supprime pas tous les problèmes de sécurité et a ses propres problèmes embêtants.
    2018-12-03 05: 36: 59Z
  

Appel d'une commande externe en Python

Simple, utilisez subprocess.run, qui renvoie un objet CompletedProcess:

 
>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

Pourquoi?

A partir de Python 3.5, la documentation recommande subprocess.run :

  

L'approche recommandée pour appeler des sous-processus consiste à utiliser la fonction run () pour tous les cas d'utilisation qu'il peut gérer. Pour des cas d'utilisation plus avancés, l'interface Popen sous-jacente peut être utilisée directement.

Voici un exemple d'utilisation la plus simple possible - et il répond exactement à la demande:

 
>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

run attend la fin de la commande, puis renvoie un objet CompletedProcess. Il peut au lieu de cela lever TimeoutExpired (si vous lui donnez un argument timeout=) ou CalledProcessError (s'il échoue et que vous passez check=True).

Comme vous pouvez le déduire de l'exemple ci-dessus, stdout et stderr sont redirigés vers votre propre stdout et stderr par défaut.

Nous pouvons inspecter l'objet renvoyé et voir la commande qui a été donnée et le code de retour:

 
>>> completed_process.args
'python --version'
>>> completed_process.returncode
0

Capture de la sortie

Si vous souhaitez capturer la sortie, vous pouvez transmettre subprocess.PIPE au stderr ou stdout approprié:

 
>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(Je trouve intéressant et légèrement contre-intuitif que les informations de version soient placées dans stderr au lieu de stdout.)

Passer une liste de commandes

On peut facilement passer de la fourniture manuelle d'une chaîne de commande (comme le suggère la question) à la fourniture d'une chaîne générée par programme. Ne construisez pas de chaînes : c’est un problème de sécurité potentiel. Il est préférable de supposer que vous ne faites pas confiance à l'entrée.

 
>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\n'

Notez que vous ne devez transmettre que args positionnellement.

Signature complète

Voici la signature réelle dans la source et comme le montre help(run):

 
def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

Les popenargs et kwargs sont donnés au constructeur Popen. input peut être une chaîne d'octets (ou unicode, si un codage spécifié ou universal_newlines=True) sera acheminé vers le stdin du sous-processus.

La documentation décrit timeout= et check=True mieux que je ne pouvais le savoir:

  

L'argument de délai d'attente est passé à Popen.communicate (). Si le délai d'attente   expire, le processus enfant sera tué et attendu. le   L'exception TimeoutExpired sera à nouveau déclenchée une fois le processus enfant terminé.   terminé.

     

Si check est vrai et que le processus se termine avec un code de sortie non nul, un   L'exception CalledProcessError sera déclenchée. Attributs de cela   exception contient les arguments, le code de sortie et stdout et stderr si   ils ont été capturés.

et cet exemple pour check=True est meilleur que celui que je pourrais trouver:

 
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Signature développée

Voici une signature étendue, indiquée dans la documentation:

 
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

Notez que cela indique que seule la liste des arguments doit être passée positionnellement. Passez donc les arguments restants en tant qu'arguments de mots clés.

Popen

Quand utiliser Popen à la place? J'aurais du mal à trouver un cas d'utilisation basé uniquement sur les arguments. L'utilisation directe de Popen vous donnerait toutefois accès à ses méthodes, notamment poll, 'send_signal', 'terminate' et 'wait'.

Voici la signature Popen indiquée dans la source . Je pense que c’est l’encapsulation la plus précise de l’information (par opposition à help(Popen)):

 
def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

Mais la documentation Popen est plus informative:

 
subprocess.Popen(args, bufsize=-1, executable=None, stdin=None,
                 stdout=None, stderr=None, preexec_fn=None, close_fds=True,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)
     

Exécuter un programme enfant dans un nouveau processus. Sur POSIX, la classe utilise   comportement semblable à os.execvp () pour exécuter le programme enfant. Sous Windows,   la classe utilise la fonction Windows CreateProcess (). Les arguments pour   Popen sont comme suit.

La compréhension de la documentation restante sur Popen restera comme un exercice pour le lecteur.

    
28
2017-10-18 16: 37: 52Z
  1. Vous trouverez un exemple simple de communication bidirectionnelle entre un processus principal et un sous-processus: stackoverflow.com/a/52841475/1349673
    2018-10-16 18: 05: 17Z
  2. Le premier exemple devrait probablement avoir shell=True ou (mieux encore) transmettre la commande sous forme de liste.
    2018-12-03 05: 16: 05Z

Utiliser:

 
import os

cmd = 'ls -al'

os.system(cmd)

os - Ce module constitue un moyen portable d’utiliser les fonctionnalités dépendant du système d’exploitation.

Pour les autres fonctions os, , ici , se trouve la documentation.

    
25
2017-05-28 23: 05: 23Z
  1. il est également obsolète. utiliser un sous-processus
    2015-12-09 18: 13: 59Z

Cela peut être aussi simple que cela:

 
import os
cmd = "your command"
os.system(cmd)
    
25
2018-06-08 12: 06: 53Z
  1. Cela ne permet pas de souligner les inconvénients, qui sont expliqués plus en détail dans 2018-12-03 05: 02: 26Z

utiliser le module os

 
import os
os.system("your command")

par exemple

 
import os
os.system("ifconfig")
    
21
2018-07-27 08: 10: 20Z
  1. Ceci duplique une réponse (légèrement) plus détaillée d'avril dernier, qui ne permet toutefois pas de signaler les mises en garde.
    2018-12-03 04: 59: 29Z

subprocess.check_call est pratique si vous ne souhaitez pas tester les valeurs de retour. Il lève une exception sur toute erreur.

    
20
2011-01-18 19: 21: 44Z

J'ai tendance à utiliser le sous-processus avec shlex (pour gérer l'échappement des chaînes citées):

 
>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)
    
20
2014-04-30 14: 37: 04Z

Il y a une autre différence ici qui n'est pas mentionnée précédemment.

subprocess.Popen exécute la commande < > en tant que sous-processus. Dans mon cas, je dois exécuter le fichier < a > qui doit communiquer avec un autre programme, < b &gt ;.

J'ai essayé le sous-processus et l'exécution a réussi. Cependant, < b > ne pouvait pas communiquer avec < a &gt ;. Tout est normal quand je cours les deux à partir du terminal.

Un de plus: (REMARQUE: kwrite se comporte différemment des autres applications. Si vous essayez ce qui suit avec Firefox, les résultats ne seront pas les mêmes.)

Si vous essayez os.system("kwrite"), le flux de programme se bloque jusqu'à ce que l'utilisateur ferme kwrite. Pour surmonter cela, j'ai essayé à la place os.system(konsole -e kwrite). Ce programme a continué de s’écouler, mais kwrite est devenu le sous-processus de la console.

N'importe qui exécute le kwrite qui n'est pas un sous-processus (c'est-à-dire qu'il doit apparaître dans le moniteur système à l'extrême gauche de l'arborescence).

    
20
2018-06-03 20: 14: 32Z
  1. Que voulez-vous dire par "Quelqu'un exécute-t-il le kwrite n'étant pas un sous-processus" ?
    2018-06-03 20: 14: 54Z

os.system ne vous permet pas de stocker les résultats. Par conséquent, si vous souhaitez stocker les résultats dans une liste ou quelque chose subprocess.call fonctionne.

    
19
2012-06-11 22: 45: 35Z

J'aime assez la shell_command pour sa simplicité. Il est construit sur le module de sous-processus.

Voici un exemple tiré de la documentation:

 
>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py  shell_command.py  test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0
    
19
2017-10-24 19: 29: 34Z

Prise sans scrupule, j'ai écrit une bibliothèque pour cela: P https://github.com/houqp/shell.py

Pour l’instant, c’est un emballage pour Popen et Shlex. Il prend également en charge les commandes de tuyauterie afin que vous puissiez les chaîner plus facilement en Python. Pour que vous puissiez faire des choses comme:

 
ex('echo hello shell.py') | "awk '{print $2}'"
    
16
2014-05-01 20: 49: 01Z

Sous Linux, si vous souhaitez appeler une commande externe qui s'exécutera indépendamment (continuera à fonctionner après la fin du script python), vous pouvez utiliser une file d'attente simple comme spouleur de tâches ou en commande

Un exemple avec le spouleur de tâches:

 
import os
os.system('ts <your-command>')

Remarques sur le spouleur de tâches (ts):

  1. Vous pouvez définir le nombre de processus simultanés à exécuter ("slots") avec:

    ts -S <number-of-slots>

  2. L'installation de ts ne nécessite pas de privilèges d'administrateur. Vous pouvez le télécharger et le compiler à partir des sources avec un simple make, l'ajouter à votre chemin et vous avez terminé.

15
2016-11-27 00: 15: 34Z
  1. ts n'est standard sur aucune distro que je connaisse, bien que le pointeur sur at soit légèrement utile. Vous devriez probablement également mentionner batch. Comme ailleurs, la recommandation os.system() devrait probablement au moins mentionner que subprocess est son remplacement recommandé.
    2018-12-03 05: 43: 45Z

Vous pouvez utiliser Popen, puis vérifier l'état de la procédure:

 
from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill()

Découvrez sous-processus.Popen .

    
14
2017-05-28 23: 01: 49Z
source placée ici