comment exécuter une commande bash dans un script python

Réponses:

16

La réponse de @ milne fonctionne, mais subprocess.call()vous donne peu de commentaires.

Je préfère utiliser subprocess.check_output()afin que vous puissiez analyser ce qui a été imprimé sur stdout:

 import subprocess
 res = subprocess.check_output(["sudo", "apt", "update"])
 for line in res.splitlines():
     # process the output line by line

check_output renvoie une erreur lors de la sortie à zéro de la commande invoquée

Veuillez noter que cela n'invoque pas bashou un autre shell si vous ne spécifiez pas l' shellargument mot - clé de la fonction (la même chose est vraie pour subprocess.call(), et vous ne devriez pas si ce n'est pas nécessaire car cela impose un risque pour la sécurité), il invoque directement le commander.

Si vous vous retrouvez à faire de nombreuses (différentes) invocations de commandes à partir de Python, vous voudrez peut-être regarder Plumbum . Avec cela, vous pouvez faire le (IMO) plus lisible:

from plumbum.cmd import sudo, apt, echo, cut

res = sudo[apt["update"]]()
chain = echo["hello"] | cut["-c", "2-"]
chain()
Anthon
la source
Est-il recommandé d'utiliser ( os.popenou os.system), ex res = os.popen('sudo apt update').read():? @Anthon
alper
1
@alper Read 0324 python.org/dev/peps/pep-0324 . Cela explique la justification de la fabrication subprocessbien os.systemet os.popendéjà existé. Ces PEP ne sont pas triviaux pour être acceptés. Plusieurs personnes y ont réfléchi beaucoup plus que vous ou moi. Et subprocesss'est amélioré depuis 2003, les autres sont toujours là pour la compatibilité descendante. Avez-vous redéfini la os.systempage de manuel: Le module de sous-processus fournit des fonctionnalités plus puissantes pour générer de nouveaux processus et récupérer leurs résultats; l'utilisation de ce module est préférable à l'utilisation de cette fonction.
Anthon
1
@alper Oui, vous pourriez. Comme je l'ai indiqué, il s'agit d'un risque potentiel pour la sécurité, donc je ne sais pas pourquoi vous pensez que c'est recommandé. Et l'invocation sudone fera qu'aggraver la situation. Peut-être que l'utilisation de python-apt est une meilleure solution (je n'ai pas étudié cela moi-même).
Anthon
1
@alper dans ce cas, jetez un œil sérieux au plumbum , cela vaut la peine de se mettre au courant de cela.
Anthon
1
@alper Si vous êtes sur Python3, vous devez le faire, sur Python2 non. Veuillez ne pas utiliser les commentaires ici comme système de chat. Si vous avez une question, postez-la comme telle.
Anthon
8

Il est possible que vous utilisiez le bash comme programme, avec le paramètre -c pour exécuter les commandes:

Exemple:

bashCommand = "sudo apt update"
output = subprocess.check_output(['bash','-c', bashCommand])
Le rasoir
la source
7

Le module de sous-processus est conçu pour ce faire:

import subprocess
subprocess.call(["sudo", "apt", "update"])

Si vous souhaitez que le script se termine si la commande échoue, vous pouvez envisager d'utiliser check_call()au lieu d'analyser le code retour vous-même:

subprocess.check_call(["sudo", "apt", "update"])
Milind Dumbare
la source
cela m'a donné la trace suivante: Traceback (most recent call last): File "/home/Dremor/test.py", line 3, in <module> subprocess.call('sudo', 'yum', 'update') File "/usr/lib64/python3.4/subprocess.py", line 537, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib64/python3.4/subprocess.py", line 767, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer (j'utilise yum car j'utilise Fedora comme OS principal)
Dremor
3
Vous avez oublié les crochets
Milind Dumbare
1
Notez également que le subprocess.call()blocage est tout en subprocess.Popen()non-blocage ..
heemayl
Qu'entendez-vous par «blocage»? @heemayl
alper
2

Vous pouvez également utiliser 'os.popen'.

Exemple:

import os

command = os.popen('ls -al')
print(command.read())
print(command.close())

Production:

total 16
drwxr-xr-x 2 root root 4096 ago 13 21:53 .
drwxr-xr-x 4 root root 4096 ago 13 01:50 ..
-rw-r--r-- 1 root root 1278 ago 13 21:12 bot.py
-rw-r--r-- 1 root root   77 ago 13 21:53 test.py

None
ricardo130
la source
0

utiliser le module de sous-processus

import subprocess
command = 'sudo apt update'
subprocess.check_call(command.split())
Fred
la source
pourquoi ai-je une erreur quand je l'utilise
aquagremlin
subprocess.check_call (["sudo", "apt", "update"])
aquagremlin
CalledProcessError Traceback (dernier appel le plus récent) <ipython-input-21-33ce645708e7> dans <module> () ----> 1 subprocess.check_call (["sudo", "apt", "update"]) / usr / lib / python2.7 / subprocess.pyc dans check_call (* popenargs, ** kwargs) 188 si cmd est None: 189 cmd = popenargs [0] -> 190 augmenter CalledProcessError (retcode, cmd) 191 return 0 192 CalledProcessError: Command '[' sudo ',' apt ',' update ']' a retourné l'état de sortie non nul 1
aquagremlin
cette erreur ne se produit que lorsque je l'exécute dans un cahier
jupyter
peut-être que je vais commencer une nouvelle question car c'est ot
aquagremlin