V. Exécution des commandes externes▲
Note de traduction : dans ce contexte, certains termes n’ont pas été francisés (Shell, wildcards, etc.).
Certaines parties affichées peuvent être différentes en fonction de votre environnement de travail, de votre nom d’utilisateur, votre répertoire de travail, etc.
V-A. Appel de commandes Shell▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#!/usr/bin/python3
import
subprocess
# Exécuter la commande externe 'date'
subprocess.call
(
'date'
)
# Passer des options et des arguments à la commande
print
(
"
\n
Today is "
, end=
""
, flush=
True
)
subprocess.call
(
['date'
, '-u'
, '+%A'
])
# Autre exemple
print
(
"
\n
Searching for 'hello world'"
, flush=
True
)
subprocess.call
(
['grep'
, '-i'
, 'hello world'
, 'hello_world.py'
])
- L’instruction import est utilisée pour charger le module subprocess qui fait partie de la bibliothèque Python standard).
- La fonction call du module subprocess est une des solutions pour appeler une commande externe.
- En passant la valeur True à l’argument flush (False par défaut), vous vous assurez que votre message sera affiché avant subprocess.call.
- Pour transmettre des arguments à la commande, une liste de chaînes de caractères est passée au lieu d'une chaîne de caractère unique.
2.
3.
4.
5.
6.
7.
$
./calling_shell_commands.py
Tue Jun 21
18
:35
:33
IST 2016
Today is Tuesday
Searching for
'hello world'
print
(
"Hello World"
)
Lecture complémentaire :
V-B. Appel de commandes Shell avec expansion▲
#!/usr/bin/python3
import
subprocess
# Exécution sans expansion
print
(
"Pas expansion shell quand shell=False"
, flush=
True
)
subprocess.call
(
['echo'
, 'Hello $USER'
])
# Exécution avec l’expansion Shell
print
(
"
\n
expansionshell quand shell=True"
, flush=
True
)
subprocess.call
(
'echo Hello $USER'
, shell=
True
)
# Echappement de la chaîne si nécessaire
print
(
"
\n
Searching for 'hello world'"
, flush=
True
)
subprocess.call
(
'grep -i
\'
hello world
\'
hello_world.py'
, shell=
True
)
- Par défaut subprocess.call n’est pas étendu (jolers du Shell), lors de l’exécution d'une substitution de commande, etc.
- Vous pouvez outrepasser ce comportement en passant la valeur True à l’argument shell.
- Notez que la commande entière est maintenant passée en tant que chaîne et non en tant que liste de chaînes.
- Les apostrophes (quotes : ')doivent être échappées (\').
- Utilisez shell=True seulement si vous êtes sûr que la commande doit être exécutée dans l’environnement Shell, sinon il pourrait y avoir une faille de sécurité.
- documentation Python – subprocess, Popen.
2.
3.
4.
5.
6.
7.
8.
9.
$ ./
shell_expansion.py
Pas d' expansion shell quand shell=False
Hello $USER
expansion shell quand shell=True
Hello learnbyexample
Recherche pour '
hello world'
print("Hello World")
- Dans certains cas, vous pouvez éviter l’échappement en alternant l’utilisation de guillemets et d’apostrophes comme suit :
# utilisation alternée d'apostrophes et de guillemets
subprocess.call
(
'grep -i "hello world" hello_world.py'
, shell=
True
)
# ou ceci
subprocess.call
(
"grep -i 'hello world' hello_world.py"
, shell=
True
)
- La redirection des sorties de commandes Shell peut être utilisée comme d’ordinaire.
# pour plus de clarté, utilisez des variables et évitez les longues chaînes dans des fonctions
cmd =
"grep -h 'test' report.log test_list.txt > grep_test.txt"
subprocess.call
(
cmd, shell=
True
)
Solution de remplacement de l’utilisation de Shell=True.
>>>
import
subprocess, os
>>>
subprocess.call
(
['echo'
, 'Hello'
, os.environ.get
(
"USER"
)])
Hello learnbyexample
0
- os.environ.get("USER") permet de récupérer la variable d’environnement USER.
- 0 est la valeur de retour / de sortie, indiquant la bonne réalisation de la commande. C'est une notification de l'interpréteur python qui affiche également la valeur de retour.
V-C. Gérer les commandes de flux sortants et les redirections▲
#!/usr/bin/python3
import
subprocess
# La sortie inclut les messages d’erreur
print
(
"Obtenir la sortie de la commande 'pwd' "
, flush=
True
)
curr_working_dir =
subprocess.getoutput
(
'pwd'
)
print
(
curr_working_dir)
# Obtenir le statut et les retours de la commande exécutée
# Toute autre valeur que `0` est considérée comme une commande ayant rencontré une erreur
ls_command =
'ls hello_world.py xyz.py'
print
(
"
\n
Appel de la commande '{}'"
.format
(
ls_command), flush=
True
)
(
ls_status, ls_output) =
subprocess.getstatusoutput
(
ls_command)
print
(
"status: {}
\n
sortie : '{}'"
.format
(
ls_status, ls_output))
# Vous pouvez supprimer les messages d’erreurs si vous le souhaitez
# subprocess.call() renvoie le statut de la commande et qui peut être utilisé
print
(
"
\n
Calling command with error msg suppressed"
, flush=
True
)
ls_status =
subprocess.call
(
ls_command, shell=
True
, stderr=
subprocess.DEVNULL)
print
(
"status: {}"
.format
(
ls_status))
- La sortie de getstatusoutput() est un de type de données tuple – plus d’informations et d’exemples dans les prochains chapitres.
- getstatusoutput() et getoutput() sont des fonctions héritées.
-
D’autres fonctions plus récentes et plus d'options de sécurité :
- documentation Python subprocess.check_output ;
- documentation Python subprocess.run.
$ ./
shell_command_output_redirections.py
Obtention de la sortie de la commande 'pwd'
/
home/
learnbyexample/
Python/
python_programs
Appel de la commande 'ls hello_world.py xyz.py'
status: 2
sortie : 'ls: cannot access xyz.py: No such file or directory
hello_world.py'
Appel de la commande avec messages d'erreur supprimés
hello_world.py
status: 2