Technologie

Python comme outil de scripting

Written by Eric Guillaume, CTO @ NEDA 8 mai 2019 17:57
Python comme outil de scripting

Introduction

Que vous soyez développeur en front-end ou spécialiste d’informatique haute performance vous utilisez quotidiennement des outils de scripting. Dans 99% des cas vous utilisez des scripts bash dont les fonctionnalités sont impressionnantes et tellement intuitive que vous ne voyez pas les limitations d’un tel outil. C’est au moment de devoir utiliser bash pour écrire une simple condition que vous vous rendez compte que bash est un language de programmation complexe à maîtriser.


La solution NEDA: utiliser le sous-module subprocess de python

Afin de palier a ce problème, chez NEDA nous avons trouvé une solution d’automatisation en utilisant python comme language de scripting. Grace à l’utilisation du module subprocess de python, nous pouvons avoir accès à la fois aux fonctionnalités bash traditionnelles et à un language de programmation facile d’usage et déjà maîtrisé.


Le tableau ci-dessous compare les différentes solutions de scripting disponible:

language de scripting
accès aux commandes bash
language de programmation facile d’usage et déjà maitrisé
bash
oui
non
python
non
oui
python + sous module ()
oui
oui


Appeller une commande shell depuis python

Afin d’utiliser la puissance du shell depuis python, il faut pouvoir y exécuter une commande, ceci peut être fait ainsi:

import subprocess

subprocess.run("ls -l", shell=True)

[email protected]  1 eguillaume  staff    25904 Apr 27 14:39 Screen Shot 2019-04-27 at 14.39.08.png

[email protected]  1 eguillaume  staff    63393 Apr 27 14:52 Screen Shot 2019-04-27 at 14.52.00.png

[email protected]  1 eguillaume  staff    38338 Apr 27 14:53 Screen Shot 2019-04-27 at 14.53.45.png

 

Si vous exécutez cette commande dans votre shell, vous obtiendrez exactement le même comportement que si vous tapiez directement la commande ls -l. Ceci signifie que les colorations paramétrée dans votre Shell seront conservées.


Appeller une commande shell content un pipe de redirection

Il est possible avec l’option shell=True d’utiliser toutes les options du shell, ceci inclus des pipes comme montré dans l’exemple suivant:

import subprocess

cmd = "ls -l | grep 14.39.08"

subprocess.run(cmd, shell=True)

 

[email protected]  1 eguillaume  staff    25904 Apr 27 14:39 Screen Shot 2019-04-27 at 14.39.08.png

Traiter 

Il est également possible de récupérer le résultat d’une commande shell et de la traiter dans python.

import subprocess

output = subprocess.check_output("ls -l", stderr=subprocess.STDOUT, shell=True, timeout=3, universal_newlines=True)

print(type(output))

print(output)

<class 'str'>

[email protected]  1 eguillaume  staff    25904 Apr 27 14:39 Screen Shot 2019-04-27 at 14.39.08.png

[email protected]  1 eguillaume  staff    63393 Apr 27 14:52 Screen Shot 2019-04-27 at 14.52.00.png

[email protected]  1 eguillaume  staff    38338 Apr 27 14:53 Screen Shot 2019-04-27 at 14.53.45.png


Exercuter le script python dans un shell

Vous pouvez également vouloir utiliser le script python en combinaison avec des commandes Shell, pour cela il faut rendre le fichier python que vous avez crée executable:

 chmod u+x ./display_files.py

Il faut ensuite ajouter le code suivant au début de votre script python afin qu’il soit automatiquement exécuté comme argument de python.

#!/usr/local/bin/python3

La commande suivante est donc possible:

./display_files.py | grep 14.39.08

[email protected]  1 eguillaume  staff    25904 Apr 27 14:39 Screen Shot 2019-04-27 at 14.39.08.png

Nous avons vu les différentes méthodes pour utiliser le module python subprocess en parallèle ave des commandes shell, nous allons maintenant faire une petite comparaison entre ces 2 languages de programmation.

Python vs bash

Voici une simple condition python, tout le monde tombera d’accord sur le fait qu’elle est très simple et intuitive a écrire:

  1. foo = 0
  2. if foo == 0:
  3.     print("FOO is equal to 0, exiting")
  4.     exit()

Voici la même condition en bash:

  1. FOO=0
  2. if [ $FOO -eq "0" ]; then
  3.   echo "FOO is equal to 0, exiting";
  4.   exit;
  5. fi


L’écrire en bash est beaucoup plus complexe et il est très facile d’effectuer une erreur de syntaxe qui changera l’opération demandée.  De plus il y a en permanence des ambiguïtés, par exemple  que se passerait-il si l’on remplaçait "0" par 0 ?

Pour éviter le cout cognitif de ces questions, il est préférable d’utiliser python.

Annexe: capturer une erreur en tant qu’exception

Il est également possible de capturer une erreur shell dynamiquement en python:

  1. import subprocess
  2. wrong_cmd = "ls-l"
  3. try:
  4.     output = subprocess.check_output(wrong_cmd, stderr=subprocess.STDOUT, \
  5.     shell=True, timeout=3, universal_newlines=True)
  6. except subprocess.CalledProcessError as exc:
  7.     print("Status : FAIL", exc.returncode, exc.output)
  8. else:
  9.     print("Output: \n{}\n".format(output))
  10. Status : FAIL 127 /bin/sh: ls-l: command not found


Conclusion

Il est maintenant très facile de mélanger des scripts python avec des commandes bash sans perdre de fonctionnalités. Chez NEDA nous avons donc décider de réaliser toute la logique de scripting en python afin de gagner en efficacité, temps et valeur.


Powered by Froala Editor