Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Scripting Python sous Linux
  3. Librairie standard et quelques autres
Extrait - Scripting Python sous Linux Développez vos outils système (2e édition)
Extraits du livre
Scripting Python sous Linux Développez vos outils système (2e édition)
2 avis
Revenir à la page d'achat du livre

Librairie standard et quelques autres

Introduction

Les chapitres précédents ont permis de découvrir les bases procédurales et objets du langage Python.

C’est à partir de ces bases que la communauté autour de Python a codé, à l’heure où la première version de ce livre a été écrite : 218 066 projets ou modules. 

Deux ans plus tard, ce n’est pas moins de 424 820 projets existants sur le Python Package Index.

Donc si jamais il vous vient l’idée d’écrire un super module, faites auparavant une recherche sur le site https://pypi.org (Python Package index).

Souvent, sur les médias où l’on parle du langage Python, on entend les mots ’librairie standard’ ou ’stdlib’.

De quoi s’agit-il exactement ?

La librairie standard est composée des modules embarqués avec le code source de Python.

Avantage évident : si Python est installé, alors le module de la librairie standard aussi.

Problème : par souci de compatibilité, les développeurs sont obligés de conserver de vieux, voire très vieux codes...

D’ailleurs, même Guido Van Rossum le dit : "A package in the stdlib has one foot in the grave" (un paquet dans la stdlib a un pied dans la tombe).

Par exemple pour les gestions des options de la ligne de commandes, il y a :...

La commande pip

pip est la commande d’installation des paquets Python intégrée dans les sources depuis la version 3.4.

Cette commande permet d’automatiser la connexion sur le site https://pypi.org/, le téléchargement, l’installation et même la compilation du module demandé.

De plus, il se charge des dépendances de chaque paquet.

La syntaxe, comme toujours, est assez simple :

pip <command> <nom_du_paquet>

Voici les commandes de bases :

pip install

pour installer un paquet

pip search

pour rechercher un paquet

pip show

pour avoir des infos sur les paquets installés

pip uninstall

pour désinstaller

Derrière cette commande de trois lettres se niche l’accès à plus de 200 000 modules Python.

Par la suite, si un module doit être téléchargé, cela sera signalé.

Pip est un outil évolué et souple, et voici maintenant la méthode pour réinstaller et/ou synchroniser les librairies d’un environnement virtuel à l’autre.

Pour obtenir une copie d’un environnement Python, il suffit d’appliquer la commande suivante depuis l’environnement source :

pip freeze > requirements.txt 

Et sur l’environnement cible :

pip install -r requirements.txt 

pour obtenir une installation des librairies.

RÉSUMÉ

pip est une commande pour rechercher...

Les modules sys et os

Deux modules se distinguent des autres : sys et os.

Il s’agit des modules les plus proches du système et par souci de compatibilité, on retrouve encore certaines fonctionnalités de bas niveau. Mais généralement, il vaut mieux chercher dans le reste de la librairie standard ou dans des modules spécifiques pour ces cas de figure.

1. Le module sys

Le module sys contient des paramètres maintenus par l’interpréteur et des fonctions fortement liées à l’interpréteur.

Voici quelques-unes des variables les plus importantes :

sys.argv

Les arguments de la ligne de commandes ; pour une gestion de ceux-ci, voir le module argparse.

sys.exit

Permet de sortir proprement du script en spécifiant le code de retour pour le shell.

sys.path

Les chemins de recherche des modules.

sys.platform

Le type de plateforme sur lequel on exécute le script ; cela permet d’importer des modules spécifiques par plateforme.

sys.ps1 et sys.ps2

Les prompts de l’interpréteur par défaut ’>>>’ et ’…’.

sys.stdin

sys.stdout

sys.stderr

Les trois descripteurs de fichiers de base utilisés par les fonctions input() et print().

2. Le module os

Le module os, lui, permet d’écrire des scripts portables, quel que soit le système d’exploitation.

Ainsi, changer le répertoire de travail ou parcourir le répertoire s’écrit toujours...

Les options de la ligne de commandes

Nous en parlions au début de ce chapitre, Python est bien fourni en modules pour la gestion de la ligne de commandes.

Il existe  :

  • getopt qui existe toujours, un transfuge du langage C.

  • optparse lui aussi existe toujours, mais marqué comme obsolète.

  • argparse recommandé par les développeurs de la librairie standard.

Et il en existe d’autres, mais argparse, qui, lui, est recommandé, n’a pas besoin de dépendance ni d’appel à pip.

Il s’utilise de cette manière :

  • Création d’un ’parser’, un objet dédié pour analyser les arguments

  • Ajout d’argument ’fichier’ avec une option courte et longue et de l’aide

  • Ajout d’argument Mode verbose

  • Lancement de l’analyse des arguments et stockage du résultat dans une variable ’options’ que l’on peut transmettre.

Voici un exemple de script :

# fichier : argparse_1.py 
 
import argparse 
 
def mon_programme(options): 
   print("Mon programme ") 
   print("Options : %s " % options ) 
 
if __name__ == '__main__': 
   ## gestion des arguments 
   parser = argparse.ArgumentParser() 
   parser.add_argument('-f', '--fichier', help='Nom de fichier'...

L’interception des signaux

La gestion des signaux n’est guère plus compliquée que le reste, car tout se trouve dans le module signal.

Le premier signal que l’on souhaite en général gérer est l’interruption SIGINT.

Il suffit :

  • d’importer le module signal,

  • de créer une fonction qui va intercepter le signal que l’on souhaite,

  • d’associer le signal à la fonction.

Exemple de script

#fichier : signal_1.py 
 
import signal 
import sys 
 
def interruption(signal, contexte): 
   print("Fermeture suite à CTRL-C") 
   sys.exit(0) 
 
signal.signal(signal.SIGINT, interruption) 
 
print("Début de la boucle infinie ...") 
while True: 
   pass 

La fonction doit accepter deux arguments : le signal concerné sous forme d’un nombre entier et le contexte d’exécution lors de l’interception du signal.

Exemple d’exécution

$ python signal_1.py 
Début de la boucle infinie ... 
^CFermeture suite à CTRL-C 

Il faut lancer le script puis utiliser la séquence CTRL-C (touche [Ctrl] + touche ’C’) pour arrêter le script.

Autre exemple pratique de l’utilisation des signaux : les alarmes.

Voici un script qui montre ce que l’on peut faire avec les alarmes ; cela nous permet...

Les fichiers temporaires

Générer des fichiers temporaires ne doit pas être une tâche fastidieuse.

Bien trop souvent, le répertoire /tmp devient une poubelle difficile à purger.

Python apporte un module dédié pour les fichiers temporaires, nous l’évoquons à présent car ce module va souvent être utilisé dans nos exemples.

Grâce à l’instruction with, le module de gestion des fichiers temporaires est devenu un vrai régal.

En effet, avec cette instruction, le fichier temporaire est automatiquement effacé, et cela marche même avec les répertoires.

Remarquez la simplicité du code :

#fichier : temp1.py 
 
import tempfile 
 
data = [ 'ligne 1\n', 'ligne 2\n', 'ligne 3\n' ] 
 
with tempfile.TemporaryFile(mode='w+') as fic: 
   fic.writelines( data )                     # écriture 
   fic.flush()                                # forcée 
   fic.seek(0)                                #...

Les modules pour les opérations sur les fichiers et les répertoires

Un certain nombre de modules sont prévus pour la gestion des répertoires et des fichiers.

Beaucoup de modules et fonctions proviennent de leur équivalent "ligne de commande" et le but n’est pas de remplacer le shell par le langage Python, mais d’utiliser les points forts de l’un pour combler ceux de l’autre.

1. os.path

C’est le module le plus ancien, et bon nombre de scripts existants se basent sur ce module.

Construire un chemin

os.path()

p = os.path(’/proc’)

Chemin absolu

os.path.abspath(’.’)  # retourne /home/chris

Changer de répertoire

os.chdir(p)

Créer un répertoire

os.mkdir( ’/tmp/test’)

Lister les fichiers

os.listdir(p)     #retourne une liste

mais il y a mieux, beaucoup mieux...

Existence d’un fichier

os.path.exists(p)    # retourne True or False

Autres fonctions sur les chemins os.path :

basename

Retourne le dernier élément du chemin

>>> os.path.basename('/tmp/test') 
'test' 
# Attention si le chemin se termine par '/' 
>>> os.path.basename('/tmp/test/') 
'' 

La fonction basename du shell renvoie ’test’.

dirname

Renvoie le nom du répertoire.

Existence et tests sur les fichiers :

os.path.exists(chemin)

Renvoie True ou false.

os.path.getsize(chemin)

Renvoie la taille en octets.

os.path.isabs(chemin)

True si c’est un chemin absolu.

os.path.isdir(chemin)

True si c’est un répertoire.

os.path.isfile(chemin)

True si c’est un fichier.

os.path.islink(chemin)

True si c’est un lien.

os.path.ismount(chemin)

True si c’est un point de montage.

os.path.samefile(c1, c2)

True si les deux chemins pointent sur le même fichier ou répertoire.

os.path.sameopenfile(df1,df2)

True si les deux descripteurs de fichiers pointent sur le même fichier ou répertoire.

Calcul de chemin à partir de variables, d’abréviations ou autre :

os.path.expandusers(chemin)

Remplace ~ ou ~utilisateur par le vrai répertoire.

os.path.expandvars(chemin)

Remplace les variables par leur valeur et construit un chemin.

os.path.split(chemin)

Décompose le chemin en liste.

os.path.join(chemin,chemin...)

Recompose un chemin.

2. shutil

Le module shutil...

La gestion des processus et sous-processus

Le module subprocess permet de lancer des processus, d’exécuter des commandes système et même de communiquer avec.

Tout d’abord, le lancement d’une commande simple :

>>> import subprocess 
>>> subprocess.run(["espeak", "bonjour"]) 
CompletedProcess(args=['espeak', 'bonjour'], returncode=0) 

Normalement, vous devriez entendre votre poste parler avec un accent anglais. 

1. Subprocess.run()

Avec subprocess.run(), on peut maîtriser beaucoup de choses.

En fait, tout ce qui nous intéresse…

Subprocess.run() permet de lancer une commande système, d’attendre la fin de la commande et de récupérer un objet CompletedProcess qui contient le résultat et le statut de la commande terminée.

Voici un petit exemple :

#fichier : subprocess/sub1.py 
 
import subprocess 
 
commande = [ "ls", "-l" ] 
 
cmd = subprocess.run(commande, universal_newlines=True, 
stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
 
print("=" * 30 ) 
print("Commande : %s " % commande ) 
print("=" * 30 ) 
print(" return code : %s " % cmd.returncode) 
print("=" * 30 ) 
print(" STDOUT : ") 
print(" %s " % cmd.stdout ) 
print("=" * 30 ) 
print(" STDERR : ") 
print(" %s " % cmd.stderr ) 
print("=" * 30 ) 

Ce qui, à l’exécution, devrait donner :

 $ python sub1.py 
============================== 
Commande : ['ls', '-l'] 
============================== 
return code : 0 
============================== 
STDOUT : 
total 16 
-rw-rw-r-- 1 chris chris  162 nov.   2 12:40 bdd1.txt 
-rw-rw-r-- 1 chris chris    0 nov.   2 09:57 fic1 
-rw-rw-r-- 1 chris chris    0 nov.   2 09:57 fic2 
-rw-rw-r-- 1 chris chris    0 nov.   2 09:57 fic3 
-rw-rw-r-- 1 chris chris  413 nov.   2 10:01 sub1.py 
-rw-rw-r-- 1 chris chris 1246 nov.   2 17:08 sub2.py 
-rw-rw-r-- 1 chris chris  997 nov.   2 17:13 sub3.py 
 
============================== 
STDERR : 
  
==============================...

Matplotlib

Matplotlib est une librairie scientifique pour générer des graphiques.

Celle-ci est tellement aboutie que quelques lignes de code permettent de générer un graphique simple.

Et tout le monde sait qu’un petit dessin vaut mieux qu’un grand discours.

Nous pouvons même dire qu’un petit bout de code vaut mieux qu’un gros paragraphe !

Voici :

# fichier : matplotlib1.py 
 
import matplotlib.pyplot as plt 
import random 
 
data = [ random.randint(5, 25) for x in range(0,20) ] 
 
plt.title(" Données Aléatoires")     # le titre 
plt.plot(data)                       # transmission des données 
plt.ylabel('Label axe des Y')        # titre de l'axe Y 
plt.xlabel('Label axe des X')        # titre de l'axe X 
plt.show()                           # Affichage 

Et encore, nous rajoutons un titre au graphique et donnons des labels aux deux axes.

Voici ce que cela donne :

images/08EI01.png

Huit lignes de code en tout, difficile de faire plus concis.

En cherchant bien...

RRDtool

Il est difficile de déterminer dans quelle section présenter Round Robin Database, car c’est un outil qui permet de stocker des données mais il permet aussi de les représenter graphiquement.

Créé à l’origine par Tobias Oetiker pour MRTG (Multi Router Traffic Grapher), RRDTool est devenu un standard industriel dans le monde OpenSource. Il est utilisé dès que l’on souhaite stocker des données sur une ligne temporelle, comme par exemple le taux d’occupation de la mémoire d’un serveur ou la température d’une salle serveur.

Ce n’est pas la librairie la plus simple à appréhender mais une fois que l’on a compris le principe, il est difficile de s’en passer.

Ce n’est pas pour rien si la plupart des outils de supervision (Nagios, Munin, Collectd etc.) l’utilisent.

L’avantage d’une base de données Round Robin est qu’elle ne varie pas en taille ; la taille du fichier sera toujours la même, par contre les données sont circulaires, les premières données seront écrasées par les dernières.

Ensuite un axe est obligatoirement temporel, le but de ce type d’outil est de stocker une ou plusieurs informations qui évoluent dans le temps sur un intervalle donné.

Avec RRDTool, le temps doit être fourni au format EPOCH : c’est le nombre de secondes écoulées depuis le 1er janvier 1970.

Voici les paramètres minimaux à renseigner pour créer un fichier RRD :

  • Un nom pour le fichier.

  • La date et heure de début au format EPOCH.

  • Un intervalle de temps en secondes (par défaut 300 = 5 minutes).

  • Une source de données avec un nom, un type et les valeurs minimales et maximales.

  • La manière de stocker ces données.

Exemple de code python

rrdtool.create(  
   "fichier.rrd",  
   "--start", "now",  
   "--step", "600",  ...

Les expressions régulières (it’s a kind of magic)

Les expressions régulières ou expressions rationnelles font partie du système Unix depuis ses débuts.

À l’origine, il s’agit d’une théorie mathématique pour décrire des ensembles. Ken Thompson lui-même (un des concepteurs d’Unix) l’a implémenté dans l’éditeur ’ed’, puis dans ’grep’.

Larry Wall a intégré dans son langage Perl des opérateurs spécifiques aux expressions régulières. Cela confère à ce langage une puissance inégalée, mais au détriment de la lisibilité du code.

Précision de l’auteur : « Il ne s’agit pas d’une critique, c’est mon humble avis et je parle d’expérience. »

Depuis, tous les langages informatiques permettent, d’une manière ou d’une autre, l’utilisation de ce formidable outil.

Guido Van Rossum aurait codé dans Python les expressions régulières suite à un échange d’idées avec Larry Wall.

Par contre, il est quasiment certain que pour le non unixien ou le commun des mortels, cela tient plus de l’incantation que de la programmation.

Mais si l’on est pragmatique, ce module permet de gagner du temps, car il permet de coder plus rapidement certains scripts répétitifs.

Avec les expressions régulières, il est possible d’exprimer en quelques lignes un code nécessitant plusieurs dizaines de lignes autrement.

La syntaxe des expressions régulières n’a rien de compliqué en soi, et, bien souvent, il suffit de tester et chercher pour trouver la solution, et parfois cela a un petit côté magique.

Vous l’aurez compris, les expressions régulières sont très appréciées de l’auteur, et une explication de cet enthousiasme se trouve en annexe de cet ouvrage.

Python utilise les expressions régulières POSIX avec quelques différences, mais ce n’est pas grave.

Maintenant que vous connaissez l’histoire des expressions régulières, il paraît judicieux de voir ce que l’on peut en faire.

Tout d’abord, une expression régulière...

Les dates et le temps (back to the future)

C’est peut-être le module qui fera la différence si vous devez choisir entre un bon vieux script bash et Python.

Effectuer des calculs sur les dates avec le shell, même si cela reste possible, n’est pas chose facile, étant donné qu’il n’a pas été conçu pour cela, et qu’à vrai dire ce n’est pas son rôle non plus.

Python se devait d’avoir des outils capables de gérer des dates, des temps et des intervalles.

Ces modules se nomment :

datetime

pour la gestion des dates et du temps

dateutil

ajoute des fonctionnalités au module datetime

time

pour la gestion du temps (notamment time.sleep)

calendar

permet de gérer un calendrier, comme la commande unix ’cal’

Mais il y en a d’autres...

1. stdlib : calendar, datetime, dateutil, time

Premier problème : savoir où se trouve la méthode qui vous intéresse dans tous ces modules.

Voici une description succincte de ces modules :

datetime

Ce module est le point de départ de la gestion des dates et du temps.

L’arithmétique est basée sur le nombre de jours.

Les points forts sont la transformation de chaîne en date et vice versa.

dateutil

Ce module ajoute des fonctionnalités au module datetime, notamment sur le calcul donné en années/mois/jours, une arithmétique plus "humaine" comme l’ajout de six mois par exemple.

S’y trouvent aussi des fonctionnalités puissantes pour le parsing de date et la gestion des TimeZones.

calendar

Ici se trouvent...

Le module logging

Ce module ne sera pas forcément utile, surtout au début, même si son utilisation est simple.

D’ailleurs, le tutoriel sur la journalisation de la documentation officielle sur python.org est du même avis, pas besoin de module logging pour un simple script, print() peut suffire.

La plupart du temps, on utilise le script de base suivant en shell :

#fichier : base_script.sh 
## ------------------- 
## Script de base 
## ------------------- 
 
BASE_DIR=$(pwd) # ou ce que vous voulez 
 
## +%j donne le no du jour dans l'année 
## Permet d'avoir un fichier par jour et un historique d'un an 
TS=$(date "+%j") 
LOG=$BASE_DIR/log/${TS}.log 
 
## On redirige les flux standards 
 
exec 2>&1 
exec 1>$LOG 
 
## ----------------------- 
## Petite routine de log 
## ----------------------- 
log() 
{ 
   msg="${1}" 
   ts=$(date "+%j %X") 
   printf ">>> ${ts} : ${msg}\n" 
} 
 
## Fonction principale 
compute() 
{ 
   echo "Je bosse ..."     # ici insérer l'appel au script 
   sleep 5                 # python shell ou autre 
} 
 
 
## ----------- 
## MAIN 
## ----------- 
log "Debut du traitement" 
compute 
log "Fin du traitement" 

Dans le fichier $BASE_DIR/log/no_du_jour.log devrait se trouver :

>>> 313 12:51:20 : Debut du traitement 
Je bosse ... 
>>> 313 12:51:25 : Fin du traitement 

Les chevrons ’>>>’ permettent de segmenter les gros logs en étapes et de les retrouver facilement.

La fonction compute est chargée de lancer les commandes, ou le script Python, ou tout autre script…

L’essentiel étant que ces commandes ou ces scripts utilisent la sortie standard et la sortie d’erreur standard pour que le script récupère...

L’accès aux fichiers en mode binaire et le module struct

Même si l’accès à des fichiers en mode binaire n’est plus franchement à la mode, il se peut que l’on se retrouve confronté à ce genre de problème à résoudre et maintenant que l’on connaît Python, on se dit qu’il doit bien y avoir une solution.

Le module struct est conçu pour transformer des octets à partir d’une structure que l’on exprimera comme un format.

Exemple : le fichier ’/var/log/wtmp’ de votre machine Linux.

Sa structure se trouve dans la page de manuel wtmp et commence comme ceci (traduit en français…) :

Type d’enregistrement

4 octets

No de processus

4 octets

Nom de device

Chaîne en C de 32 caractères maximum

Id Inittab

Chaîne en C de 4 caractères maximum

Utilisateur

Chaîne en C de 32 caractères maximum

...

 

Total 384 octets

 

Donc : il y a 4 + 4 + 32 + 4 + 32 = 76 octets et donc 308 pour aller jusqu’à 384.

L’utilisation du module struct est comme toujours assez simple.

Une fois le format défini, on peut appliquer les méthodes suivantes :

  • calcsize(structure) pour calculer la taille de l’enregistrement.

  • unpack(structure, données) pour découper les données en fonction du format.

  • pack(structure, données)...

La génération de données aléatoires

Ce module peut rendre de nombreux services pour peu que l’on prenne le temps de s’y intéresser.

Son but : fournir de fausses "bonnes" données.

Faker (c’est son nom) peut générer autant de fausses données que nécessaire.

De nos jours, la protection des données doit être un réflexe, de nombreux clients ont demandé à l’auteur de signer une charte de confidentialité sur l’ensemble de leur système informatique. Et pourtant, ils ne travaillent pas pour des secteurs stratégiques comme l’armée ou le nucléaire.

Il n’est donc plus possible de copier ou d’emprunter un fichier produits ou prospects, même une petite partie, pour effectuer des tests.

C’est là que ce module peut être utile : vous avez besoin de stresser votre gestionnaire de contacts ? Faker peut en générer 10 000… tous faux !

Voici un petit exemple :

#fichier : fake1.py 
 
from faker import Factory 
fake = Factory.create() 
 
for i in range(1,10): 
   print(fake.name()) 

Et à l’exécution :  

Alexander Perez 
David Campbell 
Jeffrey Garcia 
Lynn James 
Ashley Marshall 
Walter Santana 
Shawn Rich 
Robert Evans...

L’accès aux bases de données

Un langage informatique est un formidable outil pour exprimer des algorithmes et triturer des données. Mais le plus beau langage du monde ne peut donner que ce qu’il a.

Un script, un programme ou un traitement n’est rien sans données, et les données ne sont pas grand-chose sans scripts, programmes et traitements.

Tous les langages peuvent lire et écrire dans des fichiers et dans de multiples formats. Mais comme chaque langage a sa propre méthode (et chaque développeur aussi), très tôt dans l’histoire de l’informatique, le besoin de gérer les données à part est apparu : d’où la notion de base de données.

Au début, les données étaient stockées de manière séquentielle sur bande magnétique.

Puis les disques durs sont arrivés et cela a permis de stocker de grandes quantités de données. Mais cela a aussi permis un accès aléatoire aux données et non plus séquentiel.

De là, les bases de données sont devenues la pierre angulaire des systèmes d’information. 

D’ailleurs, une des tâches de l’ingénieur système est de sauvegarder les données. Il faut aussi sauvegarder le système d’exploitation, les configurations, etc., mais tout cela peut se reconstruire. Ce n’est pas le cas des données. De plus, avec les systèmes de gestion de bases de données relationnelle (SGBDR), il faut garantir la cohérence de ces données.

Pour faire bref, les bases de données sont importantes, mais vous le saviez déjà. Cependant, n’oubliez jamais qu’en fin de compte une base de données ne sert qu’à lire et écrire des données.

Dans la grande famille des bases de données, deux catégories se démarquent un peu plus des autres.

D’un côté, les bases de données relationnelles, où l’information doit être stockée dans des tableaux à deux dimensions, colonnes et lignes, appelées communément "tables", qui respectent la norme ACID et utilisent le langage SQL.

C’est le modèle de base le plus répandu.

ACID...

Les ORM ou Object Relationnal Mapping

Une base de données relationnelle est un peu comme une armoire avec des tiroirs et des cases.

Les données doivent rentrer dedans ; si les données n’ont pas la bonne taille, alors la base de données les rejette.

Penser ou coder "Objet", c’est un peu comme ranger ses courses dans des sacs : parfois, on doit mélanger certains objets, il y a des sacs pour les produits congelés, d’autres où l’on range les salades et les œufs, plus délicats. Certains sacs sont lourds car ils ne contiennent que les bouteilles… Et l’on manipule des tas d’objets à la fois hétérogènes et similaires.

Comment faire dialoguer efficacement ces deux mondes ?

C’est tout à fait possible, après tout, les courses finissent bien rangées dans les placards, le frigo et le congélateur.

Le SGBDR (Système de gestion de base de données relationnelle) doit se rapprocher de l’objet, et le langage-objet doit faire de même.

Cette notion se nomme ORM (Object Relationnal Mapping) ; en français : représentation objet-relationnel.

L’intérêt d’un ORM se trouve dans plusieurs points.

Le premier : cela facilite la vie au codeur. Il se retrouve à gérer des classes et non des tables, il utilise des méthodes de classe au lieu de lancer des requêtes SQL.

Le deuxième (et il doit y en avoir d’autres) : c’est l’indépendance vis-à-vis de la base de données. Un ORM fonctionne de la même manière avec SQLite, MySQL, PostgreSQL, Oracle, etc., avec peu, voire très peu de modifications sur le code.

Dans les exemples sur les bases de données, rappelez-vous le traitement des dates spécifiques. Avec un ORM, ce problème disparaît.

Il existe deux principaux paradigmes ORM : le Data Mapper pattern et l’Active Record pattern.

Tous les deux présentent les tables comme une classe.

La différence est qu’avec Active Record, la notion d’écriture dans la base se trouve au niveau de la classe, alors qu’avec Data Mapper Pattern, il faut passer par une autre classe, un Manager, représentant la session avec la base de données. 

Exemple...

Réseau

À présent que l’on sait se connecter sur des bases de données, générer des données de manière aléatoire, faire de jolis fichiers de journalisation, etc., tout cela va occuper du disque, de la RAM et du CPU.  

Il est temps de voir ce que l’on peut faire avec Python et le réseau.

Conseil de l’auteur : «  si beaucoup de notions sur le réseau TCP vous échappent, je vous préconise de visualiser le petit film « Warrior of the net » qui existe depuis très longtemps, et malgré l’ancienneté de la résolution il reste un must pour comprendre comment fonctionne Internet. »

Depuis le début, Python permet de travailler sur les sockets et même directement sur la manipulation de paquets avec la librairie Scapy.

Écrire un serveur TCP et un client TCP avec les sockets en Python a été traité des milliers de fois, et nous emmènerait un peu trop loin. On serait plus du côté du développement que du ’scripting’.  

Par contre, l’utilisation de certains protocoles de plus haut niveau avec Python permet parfois de répondre simplement à des problématiques pas toujours évidentes en shell.

D’ailleurs, nous allons commencer par quelque chose qui n’est même pas un script.

1. Un serveur web en une ligne de commande

Non le titre de cette section n’est pas une erreur, et il est possible de créer un serveur web en une ligne de commande avec un module Python. Il suffit de se placer dans un répertoire contenant des fichiers à publier et lancer la commande suivante :

python -m http.server 

Il faut alors lancer votre navigateur favori et vous connecter sur http://localhost:8000, c’est tout.

Pour peu qu’il existe un fichier index.html dans le répertoire d’où est lancée la commande, vous avez un environnement de test pour des pages statiques.

Vous devez transférer des fichiers d’une machine à une autre, mais le serveur cible ne permet que le flux HTTP… cette petite ligne de commande permet de faire beaucoup de choses.

2. Envoyer des mails

Comme à l’accoutumée, avec Python, envoyer un e-mail est plutôt simple.

On crée...

Python et Scapy : le couteau suisse du réseau

Il est possible de définir la librairie Scapy comme étant le couteau suisse version chirurgicale du paquet TCP.

Scapy doit être vue comme un framework, un ensemble de fonctions pour décortiquer, créer, analyser tout ce qui se passe sur le réseau.

Scapy est aussi un outil de test, un sniffeur réseau mais aussi un outil d’attaque pour tester la sécurité de votre réseau.

Une fois installé via pip ou avec votre gestionnaire de paquets, il faut absolument avoir les droits du super user  root pour l’utiliser.

Il faut avoir de solides connaissances sur les paquets TCP et le fonctionnement du réseau pour bénéficier pleinement de cette librairie, mais on peut aussi l’utiliser pour des besoins plus simples.

Avis de l’auteur : « Honnêtement Je n’ai pas les compétences pour juger de la qualité de scapy, j’ai découvert l’outil par un article dans un magazine et au vue de ce qu’il offre je me devais d’en parler dans cet ouvrage. »

Il y a deux manières d’utiliser Scapy : en mode ligne de commande ou en mode script.

Bien entendu, tout ce qui se fait en ligne de commande peut être fait en scripting.

La librairie vient en effet avec un shell script qui permet de lancer un interface « ligne de commande ».

Par contre, il sera nécessaire de l’appeler avec son chemin absolu pour que cela fonctionne avec sudo.

Exemple de session

$ sudo /home/chris/env/t1/bin/scapy  
[sudo] Mot de passe de chris :  
INFO: PyX dependencies are not installed ! Please install TexLive or MikTeX. 
  
                    aSPY//YASa  
            apyyyyCY//////////YCa       |  
           sY//////YSpcs  scpCY//Pp     | Welcome to Scapy  
ayp ayyyyyyySCP//Pp           syY//C    | Version 2.5.0  
AYAsAYYYYYYYY///Ps              cY//S   |  
        pCCCCY//p          cSSps y//Y   
| https://github.com/secdev/scapy  
 ...

Python et le réseau des réseaux : Internet

Vous commencez à le comprendre : grâce à ses modules, Python peut faire beaucoup de choses. Or de nos jours, tout passe par le réseau des réseaux, et, là aussi, Python a de nombreuses ressources.

Le World Wide Web offre énormément d’informations et de données. Python, avec quelques-uns des modules présentés dans cette section, devient un formidable outil de "web scraping", qui semble être le terme à la mode actuellement.

D’après Wikipédia : "Le web scraping (parfois appelé harvesting) est une technique d’extraction du contenu de sites web, via un script ou un programme, dans le but de le transformer pour permettre son utilisation dans un autre contexte."

1. Urllib : requests

Pour devenir un bon "web scraper", il faut commencer par le début, à savoir les requêtes du protocole HTTP et de sa version sécurisée HTTPS.

Tout d’abord, il faut faire attention, car il y a de nombreux modules traitant le sujet et il est facile de s’y perdre. La complexité vient du fait que tous ces modules (urllib, urllib2, urllib3) fonctionnent différemment, et sur des versions de Python différentes.

C’est pour cette raison que nous allons présenter le module requests, basé sur la librairie urllib3, fièrement nommé sur son site comme :

Requests nécessite une installation avec pip.

Petit rappel : HTTP est un protocole dont le principe est, pour le client (le navigateur en général), d’émettre des requêtes à destination d’un serveur HTTP dont le but est de répondre à ses requêtes.

Une requête HTTP spécifie une action (GET, POST…) sur une ressource : l’URL. Le sigle URL (signifiant Uniform Ressource Locator ou localisateur uniforme de ressource) est plus communément appelé "adresse web".

Dans une URL, on trouve le protocole de communication, le nom du serveur et l’emplacement de la ressource sur le serveur.

http://www.example.com/index.html

http :

Le protocole de communication HTTP

www.example.com

Le nom complet...

OpenStreetMap et Folium

Parmi les modules et librairies impressionnants que l’on peut trouver sur Python, OSMnx et folium font certainement partie des principaux.

OpenStreetMap est la carte ouverte et collaborative du monde. C’est le Wikipédia des cartes. Et avec plus d’un million de contributeurs, cette carte ne cesse de s’améliorer.

Cerise sur le gâteau, les données sont libres.

Vous pouvez trouver davantage d’informations à cette adresse : https://www.openstreetmap.fr/

Cela n’a pas échappé à certains qui ont codé une magnifique librairie : OSMnx. Celle-ci permet de télécharger toutes sortes de données à partir de la base OpenStreetMap.

La librairie folium est construite sur les forces conjuguées du langage Python et de la librairie JavaScript leaflet.js pour traiter ces données et les visualiser sur une carte issue de leaflet.

Concrètement, voici ce que l’on peut faire avec ces outils :

images/EI01-07-202.png

Une carte des restaurants de Lyon dans Google Chrome

Et voici le script qui génère cette page HTML.

#fichier:  lyon_restos.py  
  
import osmnx as ox  
import folium  
  
Lyon = [45.7578, 4.8351]  
  
tags = {'amenity': 'restaurant'}  
resto = ox.geometries_from_point( Lyon, tags=tags)  ...

Outils

Dans cette section, nous voudrions décrire quelques outils et modules qui nous ont été utiles dans quelques cas de figure, même si certains sont largement dépassés, mais sait-on jamais...

1. Pexpect

Expect est un ancien outil qui lui aussi a été utile en son temps.

Cet outil permet de lancer un binaire et de dialoguer avec lui, cela permet d’automatiser des tâches normalement manuelles.

Pexpect est un module pur Python bâti sur les mêmes principes.

L’utilisation est assez simple : on lance le binaire voulu, on attend un prompt, on envoie quelque chose, on attend autre chose, etc.

Un dialogue s’installe :

j’attends (expect)… je reçois… j’envoie (send)...

Exemple avec une connexion FTP

$ ftp speedtest.tele2.net 
Connected to speedtest.tele2.net. 
220 (vsFTPd 3.0.3) 
Name (speedtest.tele2.net:chris): anonymous 
331 Please specify the password. 
Password: 
230 Login successful. 
Remote system type is UNIX. 
Using binary mode to transfer files. 
ftp> ls 
200 PORT command successful. Consider using PASV. 
150 Here comes the directory listing. 
... 
-rw-r--r--    1 0        0         3145728 Feb 19  2016 3MB.zip 
-rw-r--r--    1 0        0        524288000 Feb 19  2016 500MB.zip 
-rw-r--r--    1 0        0        52428800 Feb 19  2016 50MB.zip 
-rw-r--r--    1 0        0          524288 Feb 19  2016 512KB.zip 
-rw-r--r--    1 0        0         5242880 Feb 19  2016 5MB.zip 
drwxr-xr-x    2 105      108         77824 Dec 15 17:25 upload 
226 Directory send OK. 
ftp> quit 
221 Goodbye. 

Le site speedtest.tele2.net permet de télécharger des fichiers de taille variable pour effectuer des tests.

Avec pexpect, c’est quasiment la même chose et il est chaudement recommandé d’effectuer les choses manuellement avant de commencer à coder.

On commence par lancer un binaire avec la méthode spawn, ce qui nous renvoie un objet ’processus...

Résumé

Ce chapitre permet de se rendre compte de l’immensité de l’écosystème Python. 

C’est aussi pour cette raison qu’il est difficile d’être exhaustif sur les librairies et les outils Python.

Et cela n’est pas près de s’arrêter : la communauté Python grossit de jour en jour.

La Programmation orientée objet (POO) a connu un âge d’or au siècle dernier dans les années 1990 ; à l’époque, cela devait être, comme d’habitude… la solution à tous les problèmes.

L’effervescence est un peu retombée depuis, mais la POO n’a pas pour autant cessé d’évoluer.

Le chapitre suivant aborde quelques notions essentielles en POO, mais aussi quelques concepts et objets du langage Python qu’il est nécessaire de connaître.