Blog ENI : Toute la veille numérique !
En raison d'une opération de maintenance, le site Editions ENI sera inaccessible le mardi 10 décembre, en début de journée. Nous vous invitons à anticiper vos achats. Nous nous excusons pour la gêne occasionnée
En raison d'une opération de maintenance, le site Editions ENI sera inaccessible le mardi 10 décembre, en début de journée. Nous vous invitons à anticiper vos achats. Nous nous excusons pour la gêne occasionnée
  1. Livres et vidéos
  2. Python et l'analyse forensique
  3. Premiers pas en Python
Extrait - Python et l'analyse forensique Récupérer et analyser les données produites par les ordinateurs
Extraits du livre
Python et l'analyse forensique Récupérer et analyser les données produites par les ordinateurs Revenir à la page d'achat du livre

Premiers pas en Python

Installation de CPython

1. Avec le gestionnaire de paquets de la distribution GNU/Linux

a. Sur GNU/Linux Debian 9

Il existe aujourd’hui deux versions stables de Python qui peuvent être proposées par un système d’exploitation. C’est notamment le cas de Debian qui permet d’installer et de faire cohabiter Python 2.7 et Python 3. Au moment de la rédaction de ce livre, sur Debian 9, la version de Python du paquet éponyme est Python 2.7. Les bibliothèques pour Python 2 seront préfixées par « python- » (par exemple python-lxml est la version Python 2 de la bibliothèque lxml).

Les paquets pour Python 3 seront quant à eux préfixés par « python3- » (python3-lxml par exemple).

Pour connaître la version précise de Python 3 empaquetée par votre distribution, vous pouvez exécuter la commande suivante :

~$ apt-cache show python3 

À l’heure actuelle, c’est la version 3.5.3 de Python qui est empaquetée par les mainteneurs de Debian.

L’installation d’un interpréteur Python3 se fait donc à l’aide de la commande suivante :

~$ apt-get install python3 

Il faut noter que le paquet python3 est un alias du paquet python3.5. En général, ce dernier fait référence à la version stable empaquetée par la distribution.

Une fois installés, les fichiers exécutables suivants se retrouvent dans le PATH : /usr/bin/python3 et /usr/bin/python3.5 (le premier étant un lien symbolique vers le second). Les bonnes pratiques voudraient que les bibliothèques pour cette version de Python soient installées dans le dossier /usr/lib/python3.5/ par les paquets de votre distribution.

L’exécutable /usr/lib/python est à l’heure actuelle un lien symbolique vers Python 2. Si l’idée de faire pointer ce lien vers un interpréteur Python 3 peut être tentante, elle est en réalité très mauvaise : certains programmes Python 2 pourraient cesser de fonctionner.

b. Autres gestionnaires de paquets

Sur les distributions basées sur Red Hat, le gestionnaire de paquets dnf (successeur de yum) permet de connaître la version de Python 3 qui est empaquetée par la distribution. Au moment de la rédaction...

Éléments de syntaxe fondamentaux

1. Les commentaires

a. Commentaire monoligne

Le caractère dièse « # » est utilisé pour indiquer le début d’un commentaire. Il peut être placé en début de ligne ou après une instruction. Un retour à la ligne en désigne la fin.

#Une ligne de commentaire 
pi = 3.14 # Une déclaration de variable commentée 

b. Les commentaires multilignes

Les commentaires multilignes sont encadrés par des délimiteurs. Il existe deux possibilités de délimiteur : composés de guillemets simples « ’ » ou composés de guillemets doubles « " ».

''' Voici un commentaire multi-lignes avec des guillemets 
   simples. Il peut contenir les caractères composant le 
délimiteur (ici ' ), à condition de ne pas le répéter plus de deux fois ''' 
 
""" Un commentaire multi-lignes 
   avec des guillemets doubles 
""" 

2. Variables

a. Nommage

Les règles de nommage pour les variables sont les règles pour tous les identifiants de Python. Elles s’appliquent non seulement aux variables, mais aussi aux fonctions, aux classes, aux modules, etc.

En considérant l’ensemble des caractères ASCII, les noms de variables peuvent contenir des lettres (majuscules et/ou minuscules), des chiffres et des sous-tirets (ou underscore : « _ »). Avec la contrainte que le premier caractère ne soit pas un chiffre.

Depuis Python 3, des caractères Unicodes sont autorisés dans les identifiants et la PEP-3131 (lien disponible à la fin de cette partie) donne plus d’information sur la liste des caractères autorisés.

b. Affectation

L’opérateur d’affectation en Python est le caractère « = ». Il affecte la valeur (opérande de droite) à une variable (opérande de gauche).

Instruction d’affectation en python

IDENTIFIANT_VARIABLE = EXPRESSION 
IDENTIFIANT1 = IDENTIFIANT2 = EXPRESSION 

Il n’existe pas de notion de « typage des variables » : au cours de son existence, une même variable pourra faire référence...

Les types de données essentiels

1. Les nombres

a. Entiers et flottants

En Python, les entiers ne sont pas représentés sur un emplacement mémoire de taille fixe et peuvent prendre des valeurs très grandes (potentiellement infinies).

Les nombres à virgule flottante sont, quant à eux, à l’image de ceux utilisés par le processeur : représentés avec une somme de fraction binaires (la mantisse), adjointe à un exposant.

Cette notation est inspirée de celle utilisée pour représenter de très petits nombres décimaux, comme la masse moyenne d’un atome de molybdène : 1.5933 * 10e-25. Ici, la mantisse est le nombre décimal 1.5933 et l’exposant (de 10) est -25. Cette notation permet de représenter un sous-ensemble des nombres réels (ou nombres décimaux) avec des ordres de grandeurs très différents, en utilisant une quantité d’information determinée : la précision de la mantisse et les bornes acceptables pour l’exposant. Ainsi, la mantisse précédente permettrait d’exprimer le nombre 1593.3 : 1.5933 * 10e2 .

Représentation d’un nombre par une somme de fractions binaires

En binaire, 0.001 est équivalent à la somme de fractions décimales

0/2 + 0/4 + 1/8 = 0,125

En revanche, le nombre décimal 0,1 n’a aucune représentation exacte sous la forme de sommes de fractions binaires. On approche cette valeur avec 0.000110011001100… en binaire (0/2 + 0/4 + 0/8 + 1/16 + ... + 1/32 + 1/256 + 1/512 + … en décimal).

Python souffre donc des limitations classiques des calculs avec des nombres flottants tels qu’implémentés par la plupart des processeurs. Une manière de s’en rendre compte est de constater que l’égalité 0,1 + 0,1 + 0,1 = 0,3 est fausse en Python. Ici, 0,1 + 0,1 + 0,1 = 0,30000000000000004.

Les entiers peuvent être exprimés en utilisant quatre bases : décimale, hexadécimale, octale et binaire.

Syntaxe des bases non décimales en Python

0(b|o|x)NOMBRE 
Avec b pour le binaire, o pour octal et x pour hexadécimal 

En raison de cette syntaxe, hormis pour zéro lui-même, il n’est pas valide d’écrire un nombre qui commencerait par des zéros...

Les structures de contrôles

1. Conditionnels et boucles

a. Les branchements conditionnels

Python dispose d’une syntaxe unique d’expressions des branchements conditionnels, de type « SI, SINON SI, SINON ». Les mots-clés if, elif et else sont utilisés pour exprimer ces concepts. Chacun de ces mots-clés est le préambule à la définition d’un nouveau bloc de code.

Un branchement conditionnel doit impérativement débuter par un bloc if. Il peut être suivi de plusieurs blocs elif, puis, éventuellement, par un dernier bloc else.

Les deux mots-clés if et elif doivent être suivis d’une expression évaluable en tant que valeur booléenne. Si l’expression est évaluée à True, le bloc est exécuté. Si aucun des blocs définis n’a été exécuté, c’est celui défini par else qui le sera.

Si l’une des expressions conditionnelles est évaluée à True, le bloc correspondant sera exécuté, mais aucune autre expression conditionnelle du branchement ne sera évaluée : il n’y a qu’un seul (ou aucun) des blocs de code défini qui sera exécuté.

Une condition simple

if EXPR: 
   # code... 

Un SI, SINON

if EXPR: 
   # code... 
else: 
   # code... 

Un branchement conditionnel complet

if EXPR1: 
   # code... 
elif EXPR2: 
   # code... 
elif EXPRX: 
   # code... 
else: 
   # code... 

L’instruction d’affectation n’étant pas l’expression d’une valeur, son utilisation est interdite dans l’expression d’un branchement conditionnel.

Interdiction de l’affectation comme expression

>>> if a = 3: 
 File "<stdin>", line 1 
   if a = 3: 
        ^ 
SyntaxError: invalid syntax 

Confondu avec :

>>> a = 3 
>>> if a == 3: 
...     print('OK') 
...  
OK 

La syntaxe de type « switch/case » n’est pas disponible en Python. Le concept est généralement de présenter les branchements en fonction de la valeur (les case) d’une...

Mécanismes d’import

1. Définitions

a. Les modules de Python

Les mécanismes d’import de Python permettent de regrouper des définitions (de fonctions, de classes, de variables, etc.) dans un fichier pour l’utiliser « plus tard » ou « ailleurs ». Ce mécanisme, courant dans les langages de programmation récents, permet d’organiser le code en le regroupant dans des fichiers et des dossiers.

Un premier élément de ce mécanisme est la représentation d’un fichier importé : les fichiers deviennent des modules. Ce sont des objets, des instances de la classe module. En plus des attributs et méthodes communs à tous les modules (comme __name__, pour ne citer que lui), ils disposent d’attributs faisant référence aux identifiants déclarés dans le fichier.

Attributs d’un module

Si un fichier contient la définition d’une variable toto d’une fonction tata et d’une classe titi ; quand ce fichier est importé, il sera représenté par un objet qui aura des attributs toto, tata et titi. Ils font référence aux éléments définis dans le fichier en question.

b. Les packages en Python

De la même manière que pour les fichiers, les dossiers peuvent, sous certaines conditions, être importés. Ils sont alors eux aussi représentés par des instances de la classe module. À ce moment, on parlera par convention de package (pour « paquet » ou « pack » en français).

Les packages n’ont pas de type propre. Sont considérés comme tel : les modules correspondant à un dossier d’un système de fichiers ou, plus largement, les modules ayant comme attributs d’autres modules.

Concrètement, pour que l’interpréteur considère un dossier comme étant un package et qu’il puisse être importé en tant que module, il faut qu’il contienne un fichier nommé __init__.py. Ce fichier est exécuté à l’import du package. Son contenu doit être syntaxiquement valide.

Un fichier vide est « valide » en Python : il ne provoque pas d’erreur à l’import....

Environnement, dépendances et communauté

1. Déploiement/installation

a. Présentation

Le but de cette section n’est pas de traiter en détail de la mise en place des solutions de déploiement de programmes Python. Il s’agira simplement de présenter les différentes (et nombreuses) solutions qui s’offrent aux développeurs.

b. Le script setup.py

Ce script, présent à la racine d’un projet Python, regroupe les différentes informations concernant le projet : liste des fichiers sources, des ressources, des dépendances, etc. Le contenu de ce fichier peut se résumer à un appel de la fonction distutils.core.setup avec les informations nécessaires en paramètres.

Ce script peut ensuite être appelé pour effectuer les différentes opérations de compilation (build) et d’installation (install). L’étape de compilation s’occupe de créer les fichiers « python-objet », des versions pré-compilées (plus rapide à importer et à interpréter) des modules et des packages. Cette étape s’occupe aussi d’appeler un compilateur C si un ou plusieurs modules sont écrits dans ce langage.

Ce script ne dispose pas d’opération de désinstallation, ce qui peut en partie expliquer l’utilisation massive des environnements virtuels avec Python (voir section Les environnements virtuels avec virtualenv).

L’étape d’installation copie les fichiers à des endroits dépendants du système d’exploitation et de l’environnement Python.

Utilisation d’un script setup.py

# Compilation 
python3 setup.py build 
# Installation 
python3 setup.py install 
# Obtenir la liste des options 
python3 setup.py -h 

c. Egg et Wheel

Ce sont les deux principaux formats de paquets Python. Les deux différences notables sont les suivantes :

  • Egg est plus ancien et empaquette les sources.

  • Wheel, plus récent, est un format binaire qui empaquette donc les fichiers binaires compilés.

Egg est le format historique des paquets Python, introduits par setuptools, un module standard de gestion de la distribution de projet Python.

Wheel est destiné à remplacer le format Egg, il est défini dans la PEP 427....