Programmer en Python3
Programmer en Python3
Programmer en Python3
Programmer
en Python 3
AC – Programmer en Python 3
Antoine Pernot
Supervisé par Alain Ploix
Objectifs du cours ix
0.1 Notes sur la mise à jour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
0.2 Fonctionnement du cours et méthode de travail . . . . . . . . . . . . . . . . . . . . ix
0.3 Installation de Python 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
0.3.1 Debian et Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
0.3.2 Microsoft Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x
2 Le flux d’instructions 7
2.1 Les scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Les types d’erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Séquences d’instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.5 Interaction utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.6 Les conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.7 Les opérateurs de comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.8 Les blocs d’instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.9 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 Factoriser le code 13
3.1 Boucles "Tant que" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.1.1 L’instruction break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.1 Les fonctions fournies par Python . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.2 Importer des modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2.3 Créer des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
iii
iv TABLE DES MATIÈRES
4 Les séquences 19
4.1 Les chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.1.1 Modifier la casse d’une chaîne de caractères . . . . . . . . . . . . . . . . . 20
4.1.2 Compter les occurrences dans une chaîne ou une liste . . . . . . . . . . . . 21
4.1.3 Rechercher et remplacer les éléments d’une chaîne . . . . . . . . . . . . . . 21
4.2 Les listes et les tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2.1 Ajouter un élément en fin de liste . . . . . . . . . . . . . . . . . . . . . . . 22
4.2.2 Modifier un élément . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2.3 Ajouter un élément au cœur de la liste . . . . . . . . . . . . . . . . . . . . 22
4.2.4 Supprimer un élément . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.5 Calculer la taille d’une séquence . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.6 Diviser une chaîne en liste . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.7 Assembler une liste en chaîne . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.8 Trier une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.9 Inverser l’ordre d’une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.10 Mélanger une liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.11 Trouver l’index d’un élément . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2.12 Copie de liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2.13 Création rapide d’une suite de nombre . . . . . . . . . . . . . . . . . . . . 25
4.3 Boucles "Pour" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.3.1 Récupérer l’élément et son indice . . . . . . . . . . . . . . . . . . . . . . . 26
4.3.2 Parcourir deux listes en même temps . . . . . . . . . . . . . . . . . . . . . 26
4.4 Les dictionnaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.4.1 Supprimer un élément . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.4.2 Lister les clés d’un dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . 28
4.4.3 Lister les valeurs d’un dictionnaire . . . . . . . . . . . . . . . . . . . . . . . 28
4.4.4 Copier un dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.4.5 Parcourir un dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.5 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7 La programmation réseau 61
7.1 Créer un serveur socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.2 Créer un client socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.3 L’exécution de fonctions en parallèle : le multithread . . . . . . . . . . . . . . . . . 62
7.4 Créer un serveur socket acceptant plusieurs clients . . . . . . . . . . . . . . . . . . 63
7.5 Créer un serveur Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
7.6 Utiliser des services Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
7.7 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
10.3.1 Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
10.3.2 Le champ de texte QLineEdit . . . . . . . . . . . . . . . . . . . . . . . . 96
10.3.3 La classe QAbstractButton . . . . . . . . . . . . . . . . . . . . . . . . . 97
10.3.4 La case à cocher QCheckBox . . . . . . . . . . . . . . . . . . . . . . . . . 98
10.3.5 Le bouton radio QRadioButton . . . . . . . . . . . . . . . . . . . . . . . . 98
10.3.6 Le bouton poussoir QPushButton . . . . . . . . . . . . . . . . . . . . . . . 98
10.3.7 La boîte de sélection QComboBox . . . . . . . . . . . . . . . . . . . . . . . 98
10.3.8 Les champs numériques QSpinBox et QDoubleSpinBox . . . . . . . . . . . 99
10.3.9 Les champs horodateurs QDateEdit, QTimeEdit et QDateTimeEdit . . . . 100
10.3.10 La zone de texte QTextEdit . . . . . . . . . . . . . . . . . . . . . . . . . 100
10.3.11 La boîte à onglets QTabWidget . . . . . . . . . . . . . . . . . . . . . . . . 101
10.3.12 La boîte à regroupement QGroupBox . . . . . . . . . . . . . . . . . . . . . 103
10.3.13 La zone de défilement QScrollArea . . . . . . . . . . . . . . . . . . . . . 103
10.3.14 Le panneau séparé QSplitter . . . . . . . . . . . . . . . . . . . . . . . . 103
10.3.15 L’affichage en liste QListWidget . . . . . . . . . . . . . . . . . . . . . . . 104
10.3.16 L’affichage en tableau QTableWidget . . . . . . . . . . . . . . . . . . . . . 104
10.3.17 L’affichage en arbre QTreeWidget . . . . . . . . . . . . . . . . . . . . . . . 105
10.3.18 La boîte de dialogue QInputDialog . . . . . . . . . . . . . . . . . . . . . 106
10.3.19 Le sélectionneur de couleur QColorDialog . . . . . . . . . . . . . . . . . . 106
10.3.20 Le sélectionneur de fontes QFontDialog . . . . . . . . . . . . . . . . . . . 107
10.3.21 Le sélectionneur de fichier QFileDialog . . . . . . . . . . . . . . . . . . . 107
10.4 Les layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
10.4.1 Le placement sur une ligne QHBoxLayout et sur une colonne QVBoxLayout . 107
10.4.2 Le placement en formulaire QFormLayout . . . . . . . . . . . . . . . . . . . 109
10.4.3 Le placement en grille QGridLayout . . . . . . . . . . . . . . . . . . . . . 109
10.5 Les fenêtres principales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
10.5.1 Application : le bloc-notes . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
10.5.2 Les actions QAction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
10.5.3 Les barres de menu QMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
10.5.4 Les barres d’outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
10.6 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Le présent document va aborder les concepts courants de la programmation, que nous allons
appliquer à l’aide du langage de programmation Python dans sa version 3. Cet ouvrage a été conçu
afin d’être utilisé en autonomie par un étudiant désireux d’apprendre à programmer mais ne disposant
pas d’antécédents dans ce domaine. Il est composé d’un cours complet pouvant être approfondi par
des recherches personnelles, de travaux dirigés (TD) et pratiques (TP) corrigés à la fin de ce livre.
ix
x OBJECTIFS DU COURS
Il vous sera également nécessaire d’utiliser un éditeur de texte. Libre à vous d’utiliser l’éditeur de
votre choix (Atom, Geany, Vim, Emacs, nano . . .).
Nous allons ensuite installer la bibliothèque PySide2, utilisée lors de ce cours. Pour cela, ouvrez
un invité de commande et saisissez :
1 p i p i n s t a l l −U P y S i d e 2
Il vous sera également nécessaire d’utiliser un éditeur de texte. Libre à vous d’utiliser l’éditeur de
votre choix (Atom, Geany, Notepad++ . . .).
Chapitre 1
Nous allons débuter ce cours en effectuant des opérations à l’aide de l’interpréteur Python.
En effet, il est possible d’utiliser Python via l’interpréteur ou en interprétant un fichier source.
L’utilisation de l’interpréteur est recommandée pour expérimenter une fonctionnalité. Il nous servira
de "cahier de brouillon" que vous pourrez utiliser tout au long de ce cours. Les chapitres ultérieurs
se concentreront sur l’écriture de scripts destinés à être sauvegardés et interprétés.
1 Python 3 . 5 . 2 ( d e f a u l t , Nov 17 2 0 1 6 , 1 7 : 0 5 : 2 3 )
2 [ GCC 5 . 4 . 0 2 0 1 6 0 6 0 9 ] on l i n u x
3 Type " h e l p " , " c o p y r i g h t " , " c r e d i t s " o r " l i c e n s e " f o r more
information .
4 >>>
Ces quelques lignes nous indiquent la version de Python (ici 3.5.2) et que l’interpréteur est prêt
à exécuter des commandes avec les caractères >>>. Dans les exemples de ce cours, ces mêmes
caractères permettent de signaler qu’on utilise l’interpréteur.
1
2 CHAPITRE 1. PREMIERS PAS AVEC PYTHON 3
Voici donc un tableau récapitulatif des différentes opérations arithmétiques de bases abordées :
Opération Syntaxe
Addition a+b
Soustraction a-b
Multiplication a*b
Division exacte a/b
Division entière a//b
Modulo a%b
Puissance (ab ) a**b
Arrondi de a avec b décimales round(a, b)
Il faut ajouter à cela les opérateurs logiques que nous aborderons plus tard. N’oubliez pas que
Python respecte la priorité des opérations mathématiques.
— Des nombres entiers (dits entiers) et des nombres réels (la virgule est symbolisée par un
point)
— Un texte (ou chaîne de caractères). Syntaxe : "Bonjour à tous"
— Des listes. Syntaxe : [17, 12.3, "Poire"]
— Des listes associatives. Syntaxe : {"produit":"Pomme","prix":14.2}
— Une fonction
— Un booléen (True = vrai et False = faux)
— ...
On parle alors de types de variables. Nous détaillerons le fonctionnement et les opérations pouvant
être effectuées sur ces différents types de variables plus tard.
Chaque variable est identifiée à partir d’un nom que vous donnez. Ce nom est à choisir afin qu’il
respecte les consignes suivantes :
— Le nom de la variable doit être court mais indiquer son contenu pour faciliter la lecture du
code.
— Ne doit pas être un nom réservé (table 1.2).
— Ne doit comporter que des lettres (a → z et A → Z), des chiffres (0 → 9) et le caractère _
(underscore). Les autres symboles sont interdits.
— Python est sensible à la casse, c’est-à-dire que les majuscules et minuscules sont distinguées
(exemple : livre, Livre et LIVRE sont des variables différentes).
— Il est vivement recommandé de nommer les variables en minuscule, y compris la première
lettre et de commencer les mots suivants avec une majuscule pour plus de lisibilité (exemple :
listeDeProduits). Dans ce cours, cette convention de nommage sera à appliquer.
Après l’exécution des lignes présentées, voici un extrait de la mémoire vive occupée par notre
programme (table 1.3) où on y retrouve deux espaces : l’espace de noms et l’espace de valeurs,
liés entre eux par un pointeur.
nombre → 25
texteBienvenue → Bonjour à tous !
pi → 3.14159
Il est cependant possible d’effectuer des affectations multiples. Un premier exemple consiste à
affecter une même valeur pour plusieurs variables :
On peut également regrouper l’affectation de valeurs à des variables avec les affectations paral-
lèles :
Il est enfin à noter qu’une variable peut contenir le résultat d’une opération :
1 l o n g u e u r R e c t a n g l e = 25
2 l a r g e u r R e c t a n g l e = 12
3 perimetreRectangle = ( longueurRectangle + largeurRectangle ) ∗ 2
La partie gauche d’un signe égal doit toujours être un nom de variable et non une
expression. Par exemple, l’instruction ageJulie + 4 = ageCharles est invalide.
Il est cependant très répandu d’avoir ce type d’expression tout à fait impossible en mathématiques :
ageMartin = ageMartin + 1. Cela permet d’ajouter 1 à la valeur de la variable ageMartin. On
dit alors qu’on incrémente ageMartin. Vous pouvez enfin réaffecter une valeur à une variable à
savoir écraser le contenu d’une variable par une autre valeur.
1.3. LA COMPOSITION D’INSTRUCTIONS 5
1.4 Aide
Pour obtenir de l’aide sur l’utilisation d’une fonction ou d’un module, tapez help(fonction)
en remplaçant fonction par la fonction ou le module recherché.
1 >>> h e l p ( p r i n t )
2 print ( . . . )
3 p r i n t ( v a l u e , . . . , s e p= ’ ’ , end= ’ \n ’ , f i l e =s y s . s t d o u t , f l u s h=
False )
4
5 P r i n t s t h e v a l u e s t o a stream , o r t o s y s . s t d o u t by d e f a u l t .
6 O p t i o n a l keyword a r g u m e n t s :
7 f i l e : a f i l e −l i k e o b j e c t ( stream ) ; d e f a u l t s to the c u r r e n t s y s .
stdout .
8 sep : s t r i n g i n s e r t e d between v a l u e s , d e f a u l t a s p a c e .
9 end : s t r i n g appended a f t e r t h e l a s t v a l u e , d e f a u l t a n e w l i n e .
10 f l u s h : whether to f o r c i b l y f l u s h the stream .
1.5 Exercices
1. Cochez les instructions valides :
3. Écrivez les instructions permettant de calculer l’aire d’un disque. La formule est A = π × R2
avec A l’aire et R le rayon du disque valant ici 5 cm. Le résultat doit être affiché sous la forme
"L’aire du disque est de XXX cm2".
Le flux d’instructions
1 #! / u s r / b i n / env p y t h o n 3
2
3 l o n g u e u r P i e c e = 17 # En mè t r e s
4 largeurPiece = 9 # En mè t r e s
5 longueurCarrelage = 0.3 # En mè t r e s
6 airePiece = longueurPiece ∗ largeurPiece
7 a i r e C a r r e a u C a r r e l a g e = l o n g u e u r C a r r e l a g e ∗∗2
8 nombreCarreauxCarrelage = a i r e P i e c e / aireCarreauCarrelage
9 p r i n t ( " I l vous f a u dr a " , nombreCarreauxCarrelage , " c a r r e a u x pour
r e c o u v r i r une p i è c e de " , a i r e P i e c e , "m2 . " )
Vous aurez remarqué qu’il s’agit des mêmes instructions que nous avons déjà rencontrées. Notez
par ailleurs l’ajout de la ligne #!/usr/bin/env python3 : cette ligne indique aux systèmes d’ex-
ploitation de type Unix qu’il s’agit d’un script Python et non d’un autre type de script (tels que
Ruby, bash . . .) et lui fournit l’adresse de l’interpréteur avec lequel lire le script (ici /usr/bin/env
python3). Il s’agit du shebang. Dans ce cours, nous imposons la présence de ce shebang.
Pour créer un nouveau script, utilisez un éditeur de texte 1 tel que Notepad++, Atom ou plus
simplement bloc-notes. Pour taper votre code source et enregistrez-le dans un fichier ayant pour
1. À ne pas confondre avec un traitement de texte tel que Word, OpenOffice.org Writer ou LibreOffice Writer.
7
8 CHAPITRE 2. LE FLUX D’INSTRUCTIONS
extension .py.
Pour exécuter un script Python, entrez la commande suivante dans votre shell Linux :
1 p y t h o n 3 m o n S c r i p t . py
Il est possible d’interrompre manuellement l’exécution d’un programme avec la combinaison des
touches CTRL et C .
Dans ce cours, il sera exigé de commenter les opérations complexes pour en définir simplement
leur fonctionnement.
2. L’indentation consiste en l’ajout de tabulations en début de ligne pour délimiter un bloc d’instructions.
2.4. SÉQUENCES D’INSTRUCTIONS 9
Il est tout aussi recommandé de renseigner une documentation sur le script ou la fonction
que vous développez pour renseigner comment elles fonctionnent et comment s’interfacer avec.
La documentation doit être saisie au début, précédée et suivie par ceci : """ (trois fois les
double-guillemets). En voici un exemple :
1 #! / u s r / b i n / env p y t h o n 3
2 " " " C a l c u l a t r i c e p o u r l a p o s e de c a r r e l a g e . " " "
3
4 l o n g u e u r P i e c e = 17 # En mè t r e s
5 largeurPiece = 9 # En mè t r e s
6 longueurCarrelage = 0.3 # En mè t r e s
7 airePiece = longueurPiece ∗ largeurPiece
8 a i r e C a r r e a u C a r r e l a g e = l o n g u e u r C a r r e l a g e ∗∗2
9 nombreCarreauxCarrelage = a i r e P i e c e / aireCarreauCarrelage
10 p r i n t ( " I l vous f a u dr a " , nombreCarreauxCarrelage , " c a r r e a u x pour
r e c o u v r i r une p i è c e de " , a i r e P i e c e , "m2 . " )
Le type de variable retourné est une chaîne de caractères. Pour la convertir en réel (dit flottant),
utilisez float(variable). Pour la convertir en entier, utilisez int(variable).
Dans le cas précédent, les lignes 4 et 5 seront exécutées si l’utilisateur saisit un nombre inférieur
à 5. La ligne 7 est exécutée si le nombre ne remplit pas cette condition. De manière plus générale,
voici la syntaxe d’une condition :
1 i f condition 1:
2 d é b u t b l o c code si la condition 1 est vraie
3 ...
4 f i n b l o c code s i la condition 1 est vraie
5 e l i f condition 2:
6 d é b u t b l o c code s i la condition 1 est fausse et la condition 2
est vraie
7 ...
8 f i n b l o c code s i la condition 1 est fausse et la condition 2 est
vraie
9 else :
10 d é b u t b l o c code s i l e s conditions 1 et 2 sont fausses
11 ...
12 f i n b l o c code s i l e s conditions 1 et 2 sont fausses
Pour cela, on utilise les instructions if (si en anglais) auxquelles on juxtapose la condition, et
terminées par " :". Cette condition est à remplir pour exécuter le bloc de code délimité par une
tabulation en début de chaque ligne.
On peut, ceci est facultatif, mettre une instruction elif (sinon si en anglais) permettant de
vérifier une seconde condition si la première est fausse. On peut chaîner autant d’instructions elif
que nécessaire.
2.7. LES OPÉRATEURS DE COMPARAISON 11
Enfin, l’instruction else (sinon en anglais), elle aussi facultative, exécute un bloc de code si les
conditions énumérées avec if et elif n’ont pas été remplies.
ment while, for, def . . .). Ces lignes d’en-tête se terminent Bloc 2
Ligne d’en-tête :
Un bloc de code est délimité par son indentation. Les Suite du bloc 2
lignes d’instructions d’un même bloc de code sont indentées Suite du bloc 1
de manière identique (possèdent le même nombre de tabula-
tions au début de celles-ci). Les blocs peuvent être imbriqués
comme l’illustre le schéma suivant : Figure 2.1 – Imbrication des blocs
2.9 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
1. Écrivez un programme demandant l’âge de l’utilisateur et affichant si celui-ci est majeur ou
mineur.
2. Écrivez un programme permettant, à partir d’un montant hors taxes saisi par l’utilisateur, de
calculer le montant de la TVA (20% du montant hors taxes) et du montant TTC (montant
hors taxes auquel on ajoute le montant de la TVA) et donnez le détail du calcul.
3. Écrivez un programme vérifiant si dans un texte saisi par l’utilisateur, celui-ci contient le mot
"fraise" ou le mot "pêche".
Factoriser le code
Plus vos programmes se complexifieront, plus le code source écrit sera volumineux. Pour y
remédier, nous allons introduire deux nouveaux concepts : les boucles et les fonctions. Nous
aborderons deux formes de boucles qui répondent à deux modes de fonctionnement différents.
Nous poursuivrons ensuite sur les fonctions fournies dans Python 3 et enfin sur comment écrire ces
fonctions soi-même. À partir de ce chapitre, la présence du shebang, de la documentation dans le
code, les noms de variables explicites et de commentaires sont obligatoires.
La boucle "tant que" ("while" en anglais) permet d’exécuter une portion de code tant que la
condition fournie est vraie. On utilise le mot while. Voici un exemple trivial permettant de mettre
en œuvre cette nouvelle fonction :
1 compteur = 1
2 w h i l e compteur <= 1 0 :
3 p r i n t ( compteur )
4 compteur = compteur + 1
La boucle n’est pas exécutée si au début la condition n’est pas remplie. Les variables constituant
la condition doivent exister avant l’exécution de la boucle.
13
14 CHAPITRE 3. FACTORISER LE CODE
1 compteur = 1
2 w h i l e compteur <= 1 0 :
3 p r i n t ( compteur )
Trans-typage
Lors de la saisie de données par l’utilisateur, la valeur retournée est une chaîne de caractères.
Pour effectuer des opérations mathématiques, il est nécessaire de la convertir en valeur entière ou
décimale. Pour ce faire, nous utiliserons les fonctions int() pour convertir en entier et float() pour
convertir en décimal. On peux également tronquer un nombre décimal avec la fonction int() :
1 s a i s i e U t i l i s a t e u r = " 75.9 "
2 valeurFlottante = float ( saisieUtilisateur )
3 valeurEntiere = int ( valeurFlottante )
À l’inverse, il est possible de convertir une donnée en chaîne de caractères avec la fonction str().
Il est possible de récupérer la valeur minimale et maximale d’une série de valeurs séparées par
des virgules avec respectivement les fonctions min() et max().
1 v a l e u r M a x i m a l e = max ( 4 , 1 7 . 8 , 1 2)
2 v a l e u r M i m i n a l e = min ( 4 , 1 7 . 8 , 1 2)
Ces fonctions sont notamment utiles lorsque l’on manipule des listes, que nous verrons plus tard.
3.2. LES FONCTIONS 15
Il est d’usage et fortement recommandé d’importer les modules en début de programme, sous le
shebang. Nous utiliserons cette convention tout au long de ce cours.
Si vous utilisez un faible nombre de fonctions d’un même module, il est recommandé d’importer
que ces dernières et ainsi faire l’économie des fonctions inutiles du module :
1 from random i m p o r t r a n d i n t , s h u f f l e # I m p o r t e l e s f o n c t i o n s r a n d i n t
e t s h u f f l e ( i n u t i l e dan s c e t e x e m p l e ) du module random
2 a l e a t o i r e = r a n d i n t ( 1 , 1 0 ) # Nombre a l é a t o i r e e n t r e 1 e t 10 i n c l u s
Si vous utilisez une grande partie des fonctions d’un module, il est très fastidieux d’importer les
fonctions une à une. Dans ce cas, on importe le module complet :
1 i m p o r t random # I m p o r t e l e module random
2 a l e a t o i r e = random . r a n d i n t ( 1 , 1 0 ) # Nombre a l é a t o i r e e n t r e 1 e t 10
i n c l u s ( f o n c t i o n du module random )
Vous pouvez également importer un autre script Python comme module. Pour cela, il faut que
votre module soit écrit dans le même dossier que votre script. Pour l’importer, utilisez l’une des deux
méthodes ci-dessus en renseignant le nom du fichier module sans son extension.
ATTENTION : Lorsque vous importez un module dans vos programmes, le code non
présent dans des fonctions ou classes s’exécute. Par exemple :
Fichier monmodule.py
1 d e f maFonction ( ) :
2 p r i n t ( " C e c i e s t ma f o n c t i o n " )
3 p r i n t ( " B o n j o u r l e monde ! " )
Fichier monscript.py
1 i m p o r t monmodule
2 p r i n t ( " Le c i e l e s t b l e u " )
Dans cet exemple, la ligne 3 du fichier monmodule.py sera exécutée lors de l’import.
16 CHAPITRE 3. FACTORISER LE CODE
La première ligne introduit notre nouvelle fonction nommée addition et nécessitant deux argu-
ments, les variables a et b. Ces variables, ainsi que celles déclarées au sein de cette fonc-
tion, ne sont valables que dans cette fonction. Le corps de la fonction, composé des lignes
2 et 3, indique d’effectuer une opération sur les variables et de retourner la valeur de la variable
resultat. L’exécution de la fonction s’arrête lors du return, même si d’autres instructions
la suivent.
Une fois la fonction définie, nous l’utilisons à la ligne 4 en lui fournissant comme arguments les
valeurs a=4 et b=7. On récupère le résultat de cette fonction dans la variable resultatAddition.
On affiche le contenu de la variable resultatAddition à la ligne 5. Si le résultat d’une fonction
n’est pas récupéré, il est perdu.
Lorsqu’une fonction est créée, elle prévaut sur celle fournie par défaut par Python. Si vous appelez
une de vos fonctions print, celle-ci sera appelée en lieu et place de celle fournie de base.
Lors de l’utilisation d’une fonction, tous les arguments sont obligatoires. Vous pouvez rendre un
argument facultatif en lui fournissant une valeur par défaut :
1 d e f t a b l e A d d i t i o n ( v a l e u r , f i n =10) :
2 compteur = 1
3 w h i l e compteur <= f i n : # Par d é f a u t , l a v a l e u r de f i n e s t à 1 0 .
4 p r i n t ( compteur , "+" , v a l e u r , "=" , compteur+v a l e u r )
5 compteur += 1 # É q u i v a l e n t à compteur = compteur + 1
3.3. EXERCICES 17
6 tableAddition (4) # La v a r i a b l e f i n a u r a p o u r v a l e u r 10
7 t a b l e A d d i t i o n ( 6 , 1 5) # La v a r i a b l e f i n a u r a p o u r v a l e u r 15
Vous pouvez fournir les arguments dans le désordre lors de l’appel d’une fonction en nommant
vos variables :
1 def addition (a , b) :
2 r e t u r n ( a+b )
3 r e s u l t a t A d d i t i o n = a d d i t i o n ( b=2, a=9)
4 print ( resultatAddition )
Ici, la fonction aura pour arguments a=9 et b=2. Ce type d’appel peut être utile pour des fonctions
ayant un grand nombre d’arguments pour plus de clarté.
Enfin, il est également possible de retourner plusieurs valeurs à la fin d’une fonction :
1 def valeursExtremes ( valeurs ) :
2 r e t u r n ( min ( v a l e u r s ) , max ( v a l e u r s ) )
3 valeurMinimale , valeurMaximale = valeursExtremes ([14 ,96 ,57 ,10 ,0.7])
3.3 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
1. Écrivez un programme permettant d’effectuer les opérations de base (+, −, ×, ÷) en mathé-
matiques en créant des fonctions.
18 CHAPITRE 3. FACTORISER LE CODE
Les séquences
Les séquences en Python sont des structures de données composées d’entités plus petites. Dans
cette catégorie, on retrouve les chaînes de caractères, les listes et les dictionnaires. Ces types
de données ont en commun des fonctions permettant d’avoir des informations sur elles ou de les
modifier, ainsi qu’une boucle parcourant un à un les éléments de celles-ci. Nous allons étudier en
détail ces structures, les fonctions, ainsi que la boucle "Pour" dans ce chapitre.
chaineDeCaracteres=" M o n t a g n e "
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
0 1 2 3 4 5 6 7
On peut donc accéder aux caractères un à un à partir de leurs indices et n’utiliser qu’une partie
de la chaîne en demandant un fragment de celle-ci :
1 >>> c h a i n e D e C a r a c t e r e s = " Montagne "
2 >>> print ( chaineDeCaracteres [ 0 ] )
3 M # Premier c a r a c t e r e
4 >>> print ( chaineDeCaracteres [ 3 ] )
5 t # Quatrieme c a r a c t e r e
6 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ −1])
7 e # Dernier caractere
8 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ −2])
9 n # Avant−d e r n i e r c a r a c t e r e
10 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ −3])
19
20 CHAPITRE 4. LES SÉQUENCES
11 g # Avant−avant −d e r n i e r c a r a c t è r e
12 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ 2 : 5 ] )
13 nta # Tranche du t r o i s i ème au c i n q u i ème c a r a c t è r e
14 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ : 4 ] )
15 Mont # Tranche du p r e m i e r au q u a t r i ème c a r a c t è r e
16 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ 6 : ] )
17 ne # Tranche du s e p t i ème au d e r n i e r c a r a c t è r e
18 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ 7 : 2 : − 1 ] )
19 engat # Tranche du h u i t i ème au t r o i s i ème c a r a c t è r e dan s l e s e n s
inverse
20 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ : : − 1 ] )
21 engatnoM # La cha î ne compl è t e d ans l e s e n s i n v e r s e
22 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ : : 2 ] )
23 Mnan # Les l e t t r e s d ’ i n d i c e p a i r
24 >>> p r i n t ( c h a i n e D e C a r a c t e r e s [ 1 : : 2 ] )
25 otge # Les l e t t r e s d ’ i n d i c e i m p a i r
Comme nous l’avons vu dans l’exemple précédent, on peut accéder aux caractères d’une chaîne
en entrant le nom de la variable suivi de l’indice entre crochets. Un indice négatif permet d’accéder
aux caractères à partir de la fin.
La syntaxe générale est : variable[indiceDebut (par défaut 0):indiceFin (par défaut la fin
de la chaîne):pas (par défaut 1)] avec indiceDebut inclus, indiceFin exclu et pas le pas.
Si une valeur n’est pas renseignée, sa valeur par défaut est appliquée. Si une seule valeur est
entrée entre crochets, seulement le caractère à l’indice du début est retourné (exemple lignes 2 à
10).
Enfin, il est possible de concaténer 1 des chaînes de caractères uniquement à l’aide du symbole
+:
La différence entre une liste et un tuple est qu’une liste est modifiable et un tuple, non. Chaque
élément est séparé par une virgule. Voici ci-dessous la syntaxe pour déclarer une liste et un tuple :
À l’instar des chaînes de caractères, on peut accéder aux éléments d’une liste ou d’un tuple par
son indice entre crochets :
1 >>> e x e m p l e L i s t e = [ 2 7 , 2 4 . 8 , " B o n j o u r " ]
2 >>> l i s t e D a n s U n e L i s t e = [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] , [ 7 , 8 , 9 ] ]
3 >>> e x e m p l e L i s t e [ 0 ]
4 27
5 >>> e x e m p l e L i s t e [ 1 : ]
6 [ 2 4 . 8 , ’ Bonjour ’ ]
7 >>> l i s t e D a n s U n e L i s t e [ 0 ]
8 [1 , 2 , 3]
9 >>> l i s t e D a n s U n e L i s t e [ 0 ] [ 1 ]
10 2
Il est possible de modifier, d’ajouter ou de supprimer une valeur d’une liste et non d’un tuple.
Nous allons aborder toutes ces opérations.
3 >>> p r i n t ( f o u r n i t u r e s )
4 [ ’ c a h i e r ’ , ’ c r a y o n ’ , ’ c a r t a b l e ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
5 >>> f o u r n i t u r e s [ 4 : 4 ] = [ " r è g l e " , " f e u i l l e s " ]
6 >>> p r i n t ( f o u r n i t u r e s )
7 [ ’ c a h i e r ’ , ’ crayon ’ , ’ c a r t a b l e ’ , ’ s t y l o ’ , ’ r è gle ’ , ’ f e u i l l e s ’ , ’
t r o u s s e ’ , ’ gomme ’ ]
La méthode remove
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ,
" stylo " ]
2 >>> f o u r n i t u r e s . remove ( " s t y l o " )
3 >>> p r i n t ( f o u r n i t u r e s )
4 [ ’ c a h i e r ’ , ’ c r a y o n ’ , ’ t r o u s s e ’ , ’ gomme ’ , ’ s t y l o ’ ]
La méthode pop
Cette méthode permet de supprimer un élément par son indice et retourne l’élément supprimé :
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ]
2 >>> e l e m e n t = f o u r n i t u r e s . pop ( 3 )
3 >>> p r i n t ( f o u r n i t u r e s )
4 [ ’ c a h i e r ’ , ’ c r a y o n ’ , ’ s t y l o ’ , ’ gomme ’ ]
5 >>> p r i n t ( e l e m e n t )
6 trousse
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ]
2 >>> p r i n t ( l e n ( f o u r n i t u r e s ) )
3 5
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ,
" stylo " ]
2 >>> f o u r n i t u r e s . i n d e x ( " s t y l o " )
3 2
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ]
2 >>> c o p i e F o u r n i t u r e s = f o u r n i t u r e s
3 >>> f o u r n i t u r e s . remove ( " c r a y o n " )
4 >>> p r i n t ( f o u r n i t u r e s )
5 [ ’ c a h i e r ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
6 >>> p r i n t ( c o p i e F o u r n i t u r e s )
7 [ ’ c a h i e r ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
Lors de la ligne 2, Python crée un alias à la nouvelle liste et n’effectue pas de copie. Chaque
opération apportée sur chaque variable affectera la liste qui est accessible par ses alias. Ainsi, pour
effectuer une véritable copie d’une liste, il est nécessaire d’utiliser la fonction deepcopy du module
copy :
1 >>> from copy i m p o r t d e e p c o p y
2 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ]
3 >>> c o p i e F o u r n i t u r e s = d e e p c o p y ( f o u r n i t u r e s )
4 >>> f o u r n i t u r e s . remove ( " c r a y o n " )
5 >>> p r i n t ( f o u r n i t u r e s )
6 [ ’ c a h i e r ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
7 >>> p r i n t ( c o p i e F o u r n i t u r e s )
8 [ ’ c a h i e r ’ , ’ c r a y o n ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
1 >>> l i s t e = [ i f o r i i n r a n g e ( 0 , 2 0 , 2 ) ]
2 >>> p r i n t ( l i s t e )
3 [ 0 , 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18]
26 CHAPITRE 4. LES SÉQUENCES
Cette syntaxe peut être utilisée pour initialiser une liste avec des valeurs identiques :
1 >>> l i s t e = [ None f o r i i n r a n g e ( 1 0 ) ]
2 >>> p r i n t ( l i s t e )
3 [ None , None , None , None , None , None , None , None , None , None ]
L’exemple ci-dessus affichera les éléments de la liste à raison de un par ligne. Il est possible
d’utiliser la fonction range directement :
1 f o r compteur i n r a n g e ( 1 5 ) :
2 p r i n t ( compteur )
1 >>> f o u r n i t u r e s = [ " c a h i e r " , " c r a y o n " , " s t y l o " , " t r o u s s e " , "gomme" ]
2 >>> f o r i n d e x , e l e m e n t i n e n u m e r a t e ( f o u r n i t u r e s ) :
3 ... p r i n t ( " I n d i c e : " + s t r ( i n d e x ) + " => " + e l e m e n t )
4 ...
5 I n d i c e : 0 => c a h i e r
6 I n d i c e : 1 => c r a y o n
7 I n d i c e : 2 => s t y l o
8 I n d i c e : 3 => t r o u s s e
9 I n d i c e : 4 => gomme
1 >>> a = [1 ,2 ,3]
2 >>> b = [4 ,5 ,6]
3 >>> c = [7 ,8 ,9]
4 >>> for i in zip (a , b , c) :
5 ... print ( i )
6 ...
7 (1 , 4 , 7)
8 (2 , 5 , 8)
9 (3 , 6 , 9)
Le dictionnaire étant un ensemble désordonné, l’ordre de déclaration des éléments qui le composent
n’a pas d’importance. Chaque élément est accessible par sa clé :
1 >>> e x e m p l e D i c t i o n n a i r e = { " l i v r e " : 7 4 , 8 5 : " t u l i p e " , 7 4 . 1 : " r o s e " , "
c o q u e l i c o t " : F a l s e , " agrumes " : [ " c i t r o n " , " o r a n g e " , " pamplemousse " ] }
2 >>> e x e m p l e D i c t i o n n a i r e [ 7 4 . 1 ]
3 ’ rose ’
4 >>> e x e m p l e D i c t i o n n a i r e [ ’ c o q u e l i c o t ’ ]
5 False
6 >>> e x e m p l e D i c t i o n n a i r e [ ’ c o q u e l i c o t ’ ] = ’ Rouge ’
7 >>> e x e m p l e D i c t i o n n a i r e [ ’ c o q u e l i c o t ’ ]
8 ’ Rouge ’
9 >>> e x e m p l e D i c t i o n n a i r e [ " agrumes " ]
10 [ ’ c i t r o n ’ , ’ o r a n g e ’ , ’ pamplemousse ’ ]
11 >>> e x e m p l e D i c t i o n n a i r e [ " agrumes " ] [ 1 ]
12 ’ o r a n g e ’
13 >>> e x e m p l e D i c t i o n n a i r e [ ’ l i v r e ’ ] += 1
14 >>> p r i n t ( e x e m p l e D i c t i o n n a i r e [ ’ l i v r e ’ ] )
15 75
4 >>> p r i n t ( q u a n t i t e F o u r n i t u r e s )
5 { ’ s t y l o s ’ : { ’ b l e u ’ : 7 4 , ’ n o i r ’ : 1 6 , ’ r o u g e ’ : 41} , ’ c a h i e r s ’ : 1 3 4 , ’
gommes ’ : 8 5 , ’ a g r a f e s ’ : 49}
On peut parcourir un dictionnaire par ses clés ou ses clés et ses valeurs avec la méthode items() :
4.5 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
3. Écrivez un programme permettant de vérifier si un mot ou une phrase saisis par l’utilisateur
est un palindrome, à savoir un mot lisible à la fois à l’endroit ou à l’envers tel que Serres,
radar, rotor ou "Ésope reste ici et se repose" :
Mélanger farine et levure, ajouter le beurre, le sucre et pétrir avec les doigts. Ajouter l’œuf
battu et le lait. Bien mélanger. Fariner la boule de pâte, étaler la pâte sur 1/2 cm et découper
des formes avec un emporte-pièce. Cuire 12 à 15 minutes à 190◦ C.
6. Écrivez un programme affichant le mot le plus long d’une phrase entrée par l’utilisateur.
4.5. EXERCICES 33
7. Écrivez un programme permettant de trier une liste de nombres sans utiliser la méthode
sort(). Réécrivez une fonction de tri de liste avec l’algorithme de tri à bulles qui consiste à
comparer deux valeurs consécutives d’une liste et de les permuter quand elles sont mal triées et
de répéter cela jusqu’à ce que la liste soit triée. Vous utiliserez les nombres tirés aléatoirement.
Il peut être nécessaire de lire ou d’écrire des fichiers stockés sur l’ordinateur exécutant vos
scripts. Consigner des données dans des fichiers permet de simplifier un programme en externalisant
les données et peut être un moyen de s’interfacer avec d’autres programmes et systèmes ainsi qu’avec
les utilisateurs. Nous utiliserons la fonction fournie par défaut open(). Avant tout, il est nécessaire
de voir comment naviguer dans l’arborescence.
Pour fermer le flux de fichier avec la méthode close() sur la variable représentant le flux.
Il est important de fermer le flux une fois les opérations sur le fichier terminé.
35
36 CHAPITRE 5. MANIPULER LES FICHIERS
Caractère Action
'r' Ouvrir en lecture seule (défaut)
'w' Ouvrir en écriture. Écrase le fichier existant.
'x' Ouvrir en écriture si et seulement si le fichier n’existe pas déjà.
'a' Ouvrir en écriture. Ajoute au fichier existant.
'b' Mode binaire.
't' Mode texte (défaut).
Chaque ligne est terminée par "\n" qui représente un retour à la ligne. Il s’agit d’un caractère
spécial. Si vous écrivez ce caractère dans une chaîne de caractères, Python produira un retour à la
ligne :
1 >>> t e x t e = " Premi è r e l i g n e \ nD eux i ème l i g n e "
2 >>> p r i n t ( t e x t e )
3 Premi è r e l i g n e
4 D e u x i ème l i g n e
Les champs texte peuvent également être délimités par des guillemets. Lorsqu’un champ contient
lui-même des guillemets, ils sont doublés afin de ne pas être considérés comme début ou fin du
champ. Si un champ contient un signe pouvant être utilisé comme séparateur de colonne (virgule,
point-virgule . . .) ou comme séparateur de ligne, les guillemets sont donc obligatoires afin que ce
signe ne soit pas confondu avec un séparateur.
Voici des données présentées sous la forme d’un tableau et d’un fichier CSV (fig. 5.1) :
(a) Données sous la forme d’un fichier CSV (b) Données sous la forme d’un tableau
Pour lire un fichier CSV, vous devez ouvrir un flux de lecture de fichier et ouvrir à partir de ce
flux un lecteur CSV. Pour ignorer la ligne d’en-tête, utilisez next(lecteurCSV) :
1 import csv
2 f i c h i e r = open ( " noms . c s v " , " r t " )
3 l e c t e u r C S V = c s v . r e a d e r ( f i c h i e r , d e l i m i t e r=" ; " ) # O u v e r t u r e du
l e c t e u r CSV en l u i f o u r n i s s a n t l e c a r a c t è r e s é p a r a t e u r ( i c i " ; " )
4 f o r l i g n e in lecteurCSV :
5 print ( ligne ) # Exemple a v e c l a 1 e l i g n e du f i c h i e r d ’ e x e m p l e :
[ ’ Nom ’ , ’ Pr énom ’ , ’ Age ’ ]
6 f i c h i e r . close ()
Vous obtiendrez en résultat une liste contenant chaque colonne de la ligne en cours. Vous pouvez
modifier le délimiteur de champs texte en définissant la variable quotechar :
1 import csv
2 f i c h i e r = open ( " noms . c s v " , " r t " )
3 l e c t e u r C S V = c s v . r e a d e r ( f i c h i e r , d e l i m i t e r=" ; " , q u o t e c h a r=" ’ " )
4 # Dé f i n i t l ’ a p o s t r o p h e comme d é l i m i t e u r de champs t e x t e
5 f o r l i g n e in lecteurCSV :
6 print ( ligne )
7 f i c h i e r . close ()
Vous pouvez également lire les données et obtenir un dictionnaire par ligne contenant les données
en utilisant DictReader au lieu de reader :
1 import csv
2 f i c h i e r = open ( " noms . c s v " , " r t " )
3 l e c t e u r C S V = c s v . D i c t R e a d e r ( f i c h i e r , d e l i m i t e r=" ; " )
4 f o r l i g n e in lecteurCSV :
5 print ( ligne ) # Ré s u l t a t o b t e n u : { ’ Age ’ : ’ 2 9 ’ , ’Nom ’ : ’ D u b o i s ’ ,
’ Pr énom ’ : ’ M a r i e ’ }
6 f i c h i e r . close ()
Il est également possible d’écrire le fichier en fournissant un dictionnaire par ligne à condition
que chaque dictionnaire possède les mêmes clés. On doit également fournir la liste des clés des
dictionnaires avec l’argument fieldnames :
1 import csv
2 bonCommande = [
3 { " p r o d u i t " : " c a h i e r " , " r e f e r e n c e " : " F452CP " , " q u a n t i t e " : 4 1 , "
prixUnitaire " :1.6} ,
4 { " p r o d u i t " : " s t y l o b l e u " , " r e f e r e n c e " : " D857BL " , " q u a n t i t e " : 1 8 , "
prixUnitaire " :0.95} ,
5 { " p r o d u i t " : " s t y l o n o i r " , " r e f e r e n c e " : "D857NO" , " q u a n t i t e " : 1 8 , "
prixUnitaire " :0.95} ,
6 { " p r o d u i t " : " é q u e r r e " , " r e f e r e n c e " : " GF955K " , " q u a n t i t e " : 4 , "
prixUnitaire " :5.10} ,
7 { " p r o d u i t " : " compas " , " r e f e r e n c e " : "RT42AX" , " q u a n t i t e " : 1 3 , "
prixUnitaire " :5.25}
8 ]
9 f i c h i e r = open ( " bon−commande . c s v " , " wt " )
10 e c r i v a i n C S V = c s v . D i c t W r i t e r ( f i c h i e r , d e l i m i t e r=" ; " , f i e l d n a m e s=
bonCommande [ 0 ] . k e y s ( ) )
11 e c r i v a i n C S V . w r i t e h e a d e r ( ) # On é c r i t l a l i g n e d ’ en−t ê t e a v e c l e
t i t r e des colonnes
12 f o r l i g n e i n bonCommande :
13 ecrivainCSV . writerow ( l i g n e )
14 f i c h i e r . c l o s e ( )
3 D857BL ; 1 8 ; s t y l o b l e u ; 0 . 9 5
4 D857NO ; 1 8 ; s t y l o n o i r ; 0 . 9 5
5 GF955K ; 4 ; é q u e r r e ; 5 . 1
6 RT42AX ; 1 3 ; compas ; 5 . 2 5
Par défaut, Python placera les guillemets autour des chaînes contenant des guillemets, une virgule
ou un point virgule afin que ceux-ci ne soient pas confondus avec un délimiteur de champs ou
le séparateur. Afin que tous les champs soient encadrés par les guillemets, nous allons modifier
l’argument quoting pour writer ou DictWriter :
1 import csv
2 f i c h i e r = open ( " a n n u a i r e . c s v " , " wt " )
3 e c r i v a i n C S V = c s v . w r i t e r ( f i c h i e r , d e l i m i t e r=" ; " , q u o t e c h a r=" ’ " ,
q u o t i n g=c s v . QUOTE_ALL) # quotechar modifie l e caract è re dé
l i m i t a n t un champ ( p a r d é f a u t : " )
4 e c r i v a i n C S V . w r i t e r o w ( [ "Nom" , " Pr énom" , "Té l é phone " ] ) # On é c r i t l a
l i g n e d ’ en−t ê t e a v e c l e t i t r e d e s c o l o n n e s
5 e c r i v a i n C S V . w r i t e r o w ( [ " D u b o i s " , " M a r i e " , " 0198546372 " ] )
6 e c r i v a i n C S V . w r i t e r o w ( [ " Duval " , " J u l i e n \" P a u l \" " , " 0399741052 " ] )
7 e c r i v a i n C S V . w r i t e r o w ( [ " J a c q u e t " , " B e r n a r d " , " 0200749685 " ] )
8 e c r i v a i n C S V . w r i t e r o w ( [ " M a r t i n " , " J u l i e ; C l a r a " , " 0399731590 " ] )
9 f i c h i e r . close ()
Valeur Action
csv.QUOTE_ALL Met tous les champs entre guillemets.
csv.QUOTE_MINIMAL Met les guillemets autour des chaînes contenant des guillemets et le
séparateur de champs (par défaut).
csv.QUOTE_NONNUMERIC Met les guillemets autour des valeurs non-numériques et indique au
lecteur de convertir les valeurs non contenues entre les guillemets en
nombres réels.
csv.QUOTE_NONE Ne met aucun guillemet.
Il ne comporte que des associations clés → valeurs (à l’instar des dictionnaires), ainsi que des
listes ordonnées de valeurs (comme les listes en Python). Une valeur peut être une autre association
clés → valeurs, une liste de valeurs, un entier, un nombre réel, une chaîne de caractères, un booléen
ou une valeur nulle. Sa syntaxe est similaire à celle des dictionnaires Python.
Il est également possible de compacter un fichier JSON en supprimant les tabulations et les retours
à la ligne. On obtient ainsi :
1 {" D i j o n " : { " nomDepartement " : " Cô t e d ’ Or " , " c o d e P o s t a l " : 2 1 0 0 0 , "
p o p u l a t i o n ":{"2006":151504 ,"2011":151672 ,"2014":153668}} ," Troyes
" : { " nomDepartement " : " Aube " , " c o d e P o s t a l " : 1 0 0 0 0 , " p o p u l a t i o n
":{"2006":61344 ,"2011":60013 ,"2014":60750}}}
Pour lire et écrire des fichiers JSON, nous utiliserons le module json fourni nativement avec
Python.
42 CHAPITRE 5. MANIPULER LES FICHIERS
Ce message signale l’erreur ainsi que la ligne à laquelle a été faite cette erreur. Or il est courant
que les erreurs ne soient pas des erreurs lors de la programmation mais une mauvaise manipulation
de la part de l’utilisateur. Par exemple, vous demandez à l’utilisateur de fournir un nombre et celui-ci
vous fournit un texte ou que le fichier, que vous cherchez à lire, n’existe pas.
Il faut alors gérer ce type d’erreurs afin d’éviter une interruption involontaire de notre application.
Pour cela, nous utiliserons les structures try.
5.4. GESTION DES ERREURS 43
Voici un exemple sur lequel nous allons ajouter un mécanisme de gestion d’erreurs :
1 age = i n p u t ( " Quel e s t v o t r e age : " )
2 age = i n t ( age )
Il est possible d’identifier l’erreur et d’effectuer une action en conséquence. Nous pouvons donc
chaîner les instructions except en fournissant le type d’erreur. Le bloc else (optionnel) est
exécuté s’il n’y a eu aucune erreur.
1 try :
2 quantiteBoites = quantitePieces / nombresPiecesParBoites
3 except TypeError : # Type i n c o m p a t i b l e a v e c l ’ op é r a t i o n
4 p r i n t ( "Au moins une d e s v a r i a b l e s n ’ e s t p a s un nombre . " )
5 e x c e p t NameError : # V a r i a b l e non d é f i n i e
6 p r i n t ( "Au moins une d e s v a r i a b l e s n ’ e s t p a s d é f i n i e . " )
7 except Z e r o D i v i s i o n E r r o r : # D i v i s i o n par 0
8 p r i n t ( " Le nombres de p i è c e s p a r b o i t e s e s t é g a l à 0 . " )
9 else :
10 p r i n t ( " I l f a u t commander " + s t r ( q u a n t i t e B o i t e s ) + " bo î t e s . " )
44 CHAPITRE 5. MANIPULER LES FICHIERS
Le bloc finally (optionnel) est exécuté dans tous les cas (s’il y a eu des erreurs ou non).
Enfin, l’instruction pass ne fait rien : elle permet de laisser un bloc vide ce qui est utile pour les
exceptions.
Dans ce chapitre, nous travaillerons sur des systèmes de fichiers Unix (GNU/Linux, MacOS . . .).
1 >>> i m p o r t o s . p a t h
2 >>> p r i n t ( o s . l i s t d i r ( " /tmp/ d i r " ) )
3 [ ’ v i l l e s . json ’ , ’ quantiteFournitures . json ’ , ’ dir2 ’ ]
1 import s h u t i l
2 s h u t i l . c o p y t r e e ( " /tmp/ d i r / d i r 2 " , " /tmp/ d i r / d i r 3 " )
3 s h u t i l . copy ( " /tmp/ d i r / d i r 2 / m o n F i c h i e r . t x t " , " /tmp/ d i r / e x e m p l e . t x t " )
1 import s h u t i l
2 s h u t i l . move ( " /tmp/ d i r / d i r 3 " , " /tmp/ d i r / p e r s o " )
1 i m p o r t os , s h u t i l
2 o s . remove ( " /tmp/ d i r / e x e m p l e . t x t " )
3 s h u t i l . r m t r e e ( " /tmp/ d i r / p e r s o " )
1 >>> i m p o r t p i c k l e
2 >>> f i c h i e r S a u v e g a r d e = open ( " d o n n e e s " , " r b " )
3 >>> t e x t e = p i c k l e . l o a d ( f i c h i e r S a u v e g a r d e )
4 >>> q u a n t i t e F o u r n i t u r e s = p i c k l e . l o a d ( f i c h i e r S a u v e g a r d e )
5 >>> f o u r n i t u r e s = p i c k l e . l o a d ( f i c h i e r S a u v e g a r d e )
6 >>> f i c h i e r S a u v e g a r d e . c l o s e ( )
7 >>> p r i n t ( t e x t e )
8 É c r i t p a r A n t o i n e de S a i n t −Exup é r y
9 >>> p r i n t ( q u a n t i t e F o u r n i t u r e s )
10 { ’ s t y l o s ’ : { ’ b l e u ’ : 7 4 , ’ r o u g e ’ : 41} , ’ gommes ’ : 8 5 , ’ c a h i e r s ’ : 134}
11 >>> p r i n t ( f o u r n i t u r e s )
12 [ ’ c a h i e r ’ , ’ c r a y o n ’ , ’ s t y l o ’ , ’ t r o u s s e ’ , ’ gomme ’ ]
5.7 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
1. Écrivez un programme permettant à un utilisateur de deviner un mot choisi au hasard dans un
fichier dans lequel chaque ligne comporte un mot en capitale. L’utilisateur a 7 chances pour
découvrir le mot en proposant une lettre à chaque fois. Si la lettre proposée n’est pas dans le
mot, une chance lui est retirée.
Exemple :
- - - - - - - - (7 chances)
Entrez une lettre : S
- - - - - - - - (6 chances)
Entrez une lettre : O
- O - - - - - - (6 chances)
...
Bravo ! Le mot était JOURNAUX.
Vous pouvez télécharger un fichier de mots ici : http://pastebin.com/raw/AXyf6C0h
5.7. EXERCICES 47
3. Écrivez un programme permettant à partir d’un fichier texte en français d’en déduire la fré-
quence d’apparition des lettres qu’il contient. Le résultat de cette analyse sera consigné dans
un fichier JSON. Pour des statistiques fiables, prenez un texte assez long. Vous pouvez utiliser
une copie de Zadig, écrit par Voltaire, disponible ici : http://pastebin.com/raw/H6AxM54J
À l’aide des statistiques d’apparition des lettres issues de l’exercice précédent, déduisez le
message en clair du texte ci-dessus.
5.7. EXERCICES 49
5. Écrivez un programme permettant de calculer la moyenne d’un étudiant dont les notes sont
consignées dans un fichier CSV. Chaque colonne correspond à une matière. Vous devrez
écrire un fichier JSON consignant ces moyennes ainsi que la moyenne générale. Toutes les
notes et les matières sont au cœfficient 1. Un exemple de fichier CSV est disponible ici :
http://pastebin.com/raw/szYzyE1k
Ce chapitre aborde les bases de données SQL. Si toutefois ce type de base de données vous est
inconnu, un chapitre permettant de vous y introduire est disponible en annexe A, page 121.
Peu à peu, nos programmes manipuleront un très grand nombre de données et nécessiteront un
système plus performant pour stocker et lire ces données. Pour cela, nous ferons appel à des bases
de données. Les bases de données permettent de stocker de grands volumes de données sous une
forme normalisée et qui peut être utilisée par plusieurs programmes différents. Nous utiliserons dans
ce cours deux SGBD gratuits :
MariaDB Copie de MySQL, disponible gratuitement et sous licence libre (GPL). Le couple MariaDB
et MySQL fait partie des SGBD les plus utilisés et les plus massivement déployés.
SQLite3 Il s’agit d’une bibliothèque écrite en C dans le domaine public permettant d’interagir avec
des bases de données stockées dans des fichiers. À l’inverse de MariaDB, il ne repose pas sur
une architecture client/serveur. Ce système est particulièrement adapté pour les petites bases
de données stockées localement, comme alternative aux fichiers texte.
51
52 CHAPITRE 6. INTERAGIR AVEC LES BASES DE DONNÉES
1 import s q l i t e 3
2 baseDeDonnees = s q l i t e 3 . c o n n e c t ( ’ c o n t a c t s . db ’ )
3 c u r s e u r = baseDeDonnees . c u r s o r ( )
4 personnes = [
5 { "nom" : " Chabot " , " prenom " : " M a r t i n " , " a d r e s s e " : " 18 r u e Gé n é r a l
L e c l e r c 13600 La C i o t a t " , " t e l e p h o n e F i x e " : " 0499506373 " } ,
6 { "nom" : " D e l b o i s " , " prenom " : " J u l i e " , " a d r e s s e " : " 35 r u e du Châ t e a u
77176 S a v i g n y l e Temple " , " t e l e p h o n e F i x e " : " 0199836074 " } ,
7 { "nom" : " R i v a r d " , " prenom " : " C h r i s t e l l e " , " a d r e s s e " : " 83 r u e de Qué
bec 83400 Hyè r e s " , " t e l e p h o n e F i x e " : " 0499687013 " }
8 ]
9 for contact in personnes :
10 c u r s e u r . e x e c u t e ( " INSERT INTO C o n t a c t s ( nom , prenom , a d r e s s e ,
t e l e p h o n e F i x e ) VALUES ( : nom , : prenom , : a d r e s s e , : t e l e p h o n e F i x e
) " , c o n t a c t ) # On a j o u t e un e n r e g i s t r e m e n t d e p u i s un
dictionnaire
11 baseDeDonnees . commit ( )
12 i d D e r n i e r E n r e g i s t r e m e n t = c u r s e u r . l a s t r o w i d # Ré cup è r e l ’ ID de l a
derni è re ligne ins é r ée .
13 baseDeDonnees . c l o s e ( )
1 import s q l i t e 3
2 baseDeDonnees = s q l i t e 3 . c o n n e c t ( ’ c o n t a c t s . db ’ )
3 c u r s e u r = baseDeDonnees . c u r s o r ( )
4 c u r s e u r . e x e c u t e ( "UPDATE C o n t a c t s SET t e l e p h o n e F i x e = ? WHERE i d = ? "
, ( " 0598635076 " , 2 ) )
5 baseDeDonnees . commit ( )
6 baseDeDonnees . c l o s e ( )
6.2. UTILISER UNE BASE DE DONNÉES MARIADB/MYSQL 53
1 >>> import s q l i t e 3
2 >>> baseDeDonnees = s q l i t e 3 . c o n n e c t ( ’ c o n t a c t s . db ’ )
3 >>> c u r s e u r = baseDeDonnees . c u r s o r ( )
4 >>> c u r s e u r . e x e c u t e ( "SELECT nom , prenom , t e l e p h o n e F i x e FROM C o n t a c t s
WHERE i d = ? " , ( " 2 " , ) )
5 >>> c o n t a c t = c u r s e u r . f e t c h o n e ( )
6 >>> p r i n t ( c o n t a c t )
7 ( ’ Chabot ’ , ’ M a r t i n ’ , ’ 0598635076 ’ )
8 >>> baseDeDonnees . c l o s e ( )
Dans l’exemple ci-dessus, la variable contact contient un tuple avec les valeurs du premier
enregistrement retourné par la requête.
1 >>> i m p o r t s q l i t e 3
2 >>> baseDeDonnees = s q l i t e 3 . c o n n e c t ( ’ c o n t a c t s . db ’ )
3 >>> c u r s e u r = baseDeDonnees . c u r s o r ( )
4 >>> c u r s e u r . e x e c u t e ( "SELECT nom , prenom , t e l e p h o n e F i x e FROM C o n t a c t s
")
5 >>> f o r c o n t a c t i n c u r s e u r . f e t c h a l l ( ) :
6 ... print ( contact )
7 ...
8 ( ’ Dupont ’ , ’ P a u l ’ , ’ 0325997452 ’ )
9 ( ’ Chabot ’ , ’ M a r t i n ’ , ’ 0598635076 ’ )
10 ( ’ D e l b o i s ’ , ’ J u l i e ’ , ’ 0199836074 ’ )
11 ( ’ R i v a r d ’ , ’ C h r i s t e l l e ’ , ’ 0499687013 ’ )
12 >>> baseDeDonnees . c l o s e ( )
1 >>> i m p o r t m y s q l . c o n n e c t o r
2 >>> baseDeDonnees = m y s q l . c o n n e c t o r . c o n n e c t ( h o s t=" l o c a l h o s t " , u s e r="
c a t a l o g u e " , p a s s w o r d=" JieTh8Th " , d a t a b a s e=" C a t a l o g u e " )
3 >>> c u r s e u r = baseDeDonnees . c u r s o r ( )
4 >>> c u r s e u r . e x e c u t e ( "SELECT r e f e r e n c e , nom , p r i x FROM P r o d u i t s " )
5 >>> f o r l i g n e i n c u r s e u r . f e t c h a l l ( ) :
6 ... print ( ligne )
7 ...
8 ( ’ ARB42 ’ , ’ Canap é deux p l a c e s n o i r ’ , 1 9 9 . 9 9 )
9 ( ’ BA9KI ’ , ’ Commode b l a n c h e ’ , 1 3 9 . 9 )
10 ( ’ EIS3P ’ , ’ C h a i s e de s a l l e à manger ’ , 2 5 . 0 )
11 ( ’IOM9X ’ , ’ L i t d o u b l e ’ , 6 9 9 . 9 9 )
12 ( ’ OI4HE ’ , ’ T a b l e b a s s e ’ , 2 4 . 9 5 )
13 >>> baseDeDonnees . c l o s e ( )
6.3 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
Vous êtes nouvellement embauché dans le secrétariat de scolarité d’une université. Votre travail
est d’optimiser la gestion des étudiants, des enseignants, des matières enseignées, des inscriptions
des étudiants à ces dernières et des résultats obtenus. À votre arrivée, une collègue vous fournit les
fichiers tableurs permettant d’accomplir ces tâches (au format CSV) :
Liste des étudiants http://pastebin.com/raw/xa3xRUu0
Liste des enseignants http://pastebin.com/raw/APUXnsjD
Liste des matières http://pastebin.com/raw/PfESUMvm
Liste des inscriptions http://pastebin.com/raw/Fc7wc8Ec
Relevé des résultats http://pastebin.com/raw/yAMkwg6h
Les exercices suivant permettront d’effectuer cela en scindant le travail en différentes sous-tâches.
Chaque sous-tâche fera l’objet d’un nouveau programme. Tous ces programmes utiliseront la même
base de données SQLite3. Toutes les moyennes auront deux décimales.
56 CHAPITRE 6. INTERAGIR AVEC LES BASES DE DONNÉES
1. Écrivez un programme permettant de créer une base de données SQLite3 nommée universite.db
et de créer la structure de table adaptée au stockage des données. Importez le contenu des
fichiers CSV dans cette base.
6.3. EXERCICES 57
2. Écrivez un programme permettant de générer des statistiques pour l’université au format JSON
dont nous stockerons les moyennes par matière, la moyenne maximale et minimale par matière,
le nombre d’étudiants inscrits par matière, la moyenne de toutes les matières et le nombre
d’étudiants par département (les deux premiers nombres du code postal).
58 CHAPITRE 6. INTERAGIR AVEC LES BASES DE DONNÉES
3. Écrivez un programme permettant de générer un bulletin de notes par étudiant sous la forme
d’un courrier stocké dans un fichier texte individuel. Chaque fichier aura pour nom le nom et
le prénom de l’étudiant, séparés par un trait d’union (-) et pour extension .txt et sera stocké
dans un dossier créé pour cela. Chaque courrier adoptera ce modèle :
La programmation réseau
Nos programmes peuvent à présent effectuer des tâches complexes et peuvent s’interfacer entre
eux par le biais de fichiers ou de bases de données. Voyons à présent comment faire communiquer
plusieurs programmes fonctionnant sur des ordinateurs différents via le réseau informatique. L’objectif
de ce chapitre est d’aborder la communication entre plusieurs ordinateurs avec le mécanisme de
sockets.
Un socket, que nous pouvons traduire par connecteur réseau, est une interface aux services réseaux
offerte par le système d’exploitation permettant d’exploiter facilement le réseau. Cela permet d’initier
une session TCP, d’envoyer et de recevoir des données par cette session. Nous utiliserons pour ce
chapitre le module socket.
Nous travaillerons avec deux scripts, le serveur permettant d’écouter les demandes des clients
et d’y répondre. Le client se connectera sur le serveur pour demander le service. Il est possible
d’exécuter à la fois le client et le serveur sur un même ordinateur. Pour cela, il vous suffit de
renseigner 127.0.0.1 comme adresse IP pour la partie client.
61
62 CHAPITRE 7. LA PROGRAMMATION RÉSEAU
10 p r i n t ( r e q u e t e . d e c o d e ( " u t f −8" ) )
11 r e p o n s e = " Bonjour , j e s u i s l e s e r v e u r "
12 c l i e n t . s e n d ( r e p o n s e . e n c o d e ( " u t f −8" ) )
13 p r i n t ( " Connexion ferm é e " )
14 c l i e n t . close ()
15 s e r v e u r . c l o s e ( )
1 #! / u s r / b i n / env p y t h o n 3
2 import socket
3 adresseIP = " 127.0.0.1 " # Ici , l e poste l o c a l
4 p o r t = 50000 # Se c o n n e c t e r s u r l e p o r t 50000
5 c l i e n t = s o c k e t . s o c k e t ( s o c k e t . AF_INET , s o c k e t . SOCK_STREAM)
6 c l i e n t . connect (( adresseIP , port ) )
7 p r i n t ( " Connect é au s e r v e u r " )
8 c l i e n t . s e n d ( " Bonjour , j e s u i s l e c l i e n t " . e n c o d e ( " u t f −8" ) )
9 reponse = c l i e n t . recv (255)
10 p r i n t ( r e p o n s e . d e c o d e ( " u t f −8" ) )
11 p r i n t ( " Connexion ferm é e " )
12 c l i e n t . close ()
Cela fonctionne mais le serveur présente un défaut, il ne peux pas gérer plusieurs clients à la fois.
Nous allons y remédier dans la suite de ce chapitre.
Nous abordons cette technique pour pouvoir élaborer un serveur pouvant gérer plusieurs connexions
client en même temps. Tout d’abord, nous allons nous familiariser avec le module threading qui met
7.4. CRÉER UN SERVEUR SOCKET ACCEPTANT PLUSIEURS CLIENTS 63
en œuvre le multithread pour les fonctions et les objets Python. Voici un exemple simple montrant
le fonctionnement de cette technique :
1 #! / u s r / b i n / env p y t h o n 3
2 import threading
3 d e f compteur ( nomThread ) :
4 f o r i in range (3) :
5 p r i n t ( nomThread + " : " + s t r ( i ) )
6 t h r e a d A = t h r e a d i n g . Thread ( None , compteur , None , ( " Thread A" , ) , {})
7 t h r e a d B = t h r e a d i n g . Thread ( None , compteur , None , ( " Thread B" , ) , {})
8 threadA . s t a r t ()
9 threadB . s t a r t ()
Voici un des résultats possibles lors de l’exécution du script ci-dessus. On observe que l’affichage
du thread A et B sont confondus :
1 Thread A : 0
2 Thread A : 1
3 Thread B : 0
4 Thread B : 1
5 Thread A : 2
6 Thread B : 2
3 import threading
4 threadsClients = []
5 def instanceServeur ( client , i n f o s C l i e n t ) :
6 adresseIP = infosClient [0]
7 port = s t r ( i n f o s C l i e n t [ 1 ] )
8 p r i n t ( " I n s t a n c e de s e r v e u r p r ê t p o u r " + a d r e s s e I P + " : " + p o r t )
9 message = " "
10 w h i l e message . u p p e r ( ) != " FIN " :
11 message = c l i e n t . r e c v ( 2 5 5 ) . d e c o d e ( " u t f −8" )
12 p r i n t ( " Message r e ç u du c l i e n t " + a d r e s s e I P + " : " + p o r t + " :
" + message )
13 c l i e n t . s e n d ( " Message r e ç u " . e n c o d e ( " u t f −8" ) )
14 p r i n t ( " Connexion ferm é e avec " + a d r e s s e I P + " : " + p o r t )
15 c l i e n t . close ()
16 s e r v e u r = s o c k e t . s o c k e t ( s o c k e t . AF_INET , s o c k e t . SOCK_STREAM)
17 s e r v e u r . b i n d ( ( ’ ’ , 50000) ) # É c o u t e s u r l e p o r t 50000
18 s e r v e u r . l i s t e n ( 5 )
19 w h i l e True :
20 c l i e n t , i n f o s C l i e n t = serveur . accept ()
21 t h r e a d s C l i e n t s . append ( t h r e a d i n g . Thread ( None , i n s t a n c e S e r v e u r ,
None , ( c l i e n t , i n f o s C l i e n t ) , {}) )
22 t h r e a d s C l i e n t s [ −1]. s t a r t ()
23 s e r v e u r . c l o s e ( )
1 #! / u s r / b i n / env p y t h o n 3
2 import socket
3 adresseIP = " 127.0.0.1 " # Ici , l e poste l o c a l
4 p o r t = 50000 # Se c o n n e c t e r s u r l e p o r t 50000
5 c l i e n t = s o c k e t . s o c k e t ( s o c k e t . AF_INET , s o c k e t . SOCK_STREAM)
6 c l i e n t . connect (( adresseIP , port ) )
7 p r i n t ( " Connect é au s e r v e u r " )
8 p r i n t ( " Tapez FIN p o u r t e r m i n e r l a c o n v e r s a t i o n . " )
9 message = " "
10 w h i l e message . u p p e r ( ) != " FIN " :
11 message = i n p u t ( "> " )
12 c l i e n t . s e n d ( message . e n c o d e ( " u t f −8" ) )
13 reponse = c l i e n t . recv (255)
14 p r i n t ( r e p o n s e . d e c o d e ( " u t f −8" ) )
15 p r i n t ( " Connexion ferm é e " )
16 c l i e n t . close ()
7.5. CRÉER UN SERVEUR WEB 65
À chaque nouvelle connexion d’un client, le serveur crée un thread dédié à ce client, ce qui permet
au programme principal d’attendre la connexion d’un nouveau client. Chaque client peut alors avoir
une conversation avec le serveur sans bloquer les autres conversations.
1 I n s t a n c e de s e r v e u r p r ê t p o u r 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2
2 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2 : Je s u i s c l i e n t 1
3 I n s t a n c e de s e r v e u r p r ê t p o u r 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5
4 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5 : Je s u i s c l i e n t 2
5 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2 : On
6 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5 : peux
7 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2 : e n v o y e r
8 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5 : d e s
9 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2 : m e s s a g e s
10 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5 : e n s e m b l e
11 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2 : FIN
12 Connexion ferm é e avec 1 2 7 . 0 . 0 . 1 : 5 7 2 8 2
13 Message r e ç u du c l i e n t 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5 : FIN
14 Connexion ferm é e avec 1 2 7 . 0 . 0 . 1 : 5 7 3 6 5
Nous allons ici utiliser la bibliothèque http.server pour créer rapidement un serveur Web capable
de servir des fichiers à un navigateur Web. Le script ci-dessous montre comment créer cela en
spécifiant le numéro de port sur lequel notre serveur Web va écouter et quel dossier il va servir.
1 import http . s e r v e r
2 p o r t E c o u t e = 80 # P o r t Web p a r d é f a u t
3 adresseServeur = ( "" , portEcoute )
4 s e r v e u r = h t t p . s e r v e r . HTTPServer
5 h a n d l e r = h t t p . s e r v e r . CGIHTTPRequestHandler
6 h a n d l e r . c g i _ d i r e c t o r i e s = [ " /tmp " ] # On s e r t l e d o s s i e r /tmp
7 p r i n t ( " Serveur a c t i f sur l e port " , portEcoute )
8 httpd = se rv eur ( adresseServeur , handler )
9 httpd . se rv e_ f or ev er ()
Ce serveur retournera par défaut le fichier index.html du dossier servi. Si ce fichier n’existe pas,
le serveur retournera la liste des fichiers du dossier.
66 CHAPITRE 7. LA PROGRAMMATION RÉSEAU
Nous allons voir comment utiliser des services Web proposés pour enrichir nos applications Python
en utilisant le module urllib.request. Notre premier exemple sera d’afficher la position de la
Station Spatiale Internationale (ISS) qui nous est fournie par l’API http://api.open-notify.
org/iss-now.json qui nous renvoie un texte au format JSON sous cette forme :
1 {
2 " iss_position ": {
3 " l o n g i t u d e " : " −100.8325" ,
4 " l a t i t u d e " : " −12.0631"
5 },
6 " t i m e s t a m p " : 1493971107 ,
7 " message " : " s u c c e s s "
8 }
Voici le code source permettant de récupérer la donnée et en récupérer les parties utiles :
1 import u r l l i b . request
2 import json
3 r e q u e t e = u r l l i b . r e q u e s t . R e q u e s t ( ’ h t t p : / / a p i . open−n o t i f y . o r g / i s s −now
. json ’ ) # La r e q u ê t e de l ’ API
4 r e p o n s e = u r l l i b . r e q u e s t . u r l o p e n ( r e q u e t e ) # Ré cup é r e r l e f i c h i e r
JSON
5 d o n n e e s B r u t = r e p o n s e . r e a d ( ) . d e c o d e ( " u t f −8" ) # Dé c o d e r l e t e x t e r e ç u
6 donneesJSON = j s o n . l o a d s ( d o n n e e s B r u t ) # Dé c o d e r l e f i c h i e r JSON
7 p o s i t i o n = donneesJSON [ " i s s _ p o s i t i o n " ]
8 p r i n t ( " La s t a t i o n s p a t i a l e i n t e r n a t i o n a l e e s t s i t u é e à une l o n g i t u d e
" + p o s i t i o n [ " l o n g i t u d e " ] + " e t à une l a t i t u d e " + p o s i t i o n [ "
latitude " ] + " . ")
Nous allons utiliser une seconde API permettant de trouver les communes associées à un code
postal. L’API http://api.zippopotam.us/FR/XXXXX où XXXXX est le code postal recherché. Voici
un exemple de données retournées :
1 {
2 " p o s t code " : " 2 1 0 0 0 " ,
3 " country " : " France " ,
7.7 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
Vous êtes nouvellement embauché dans une banque pour mettre au point le système de commu-
nication entre les distributeurs automatiques et le système central de gestion des comptes. Votre
travail est de développer les applications sur ces deux systèmes pour permettre aux distributeurs de
communiquer avec le système central pour effectuer les transactions.
On souhaite créer une base de données SQLite3 stockant les soldes des comptes, les informations
les concernant, ainsi que les transactions effectuées. On utilisera un serveur de socket pour effectuer
les communications entre les deux systèmes. Voici les différents messages pris en charge avec (C→S)
un message du client vers le serveur et (S→C) un message du serveur vers le client :
— TESTPIN numeroCompte codePIN (C→S) : Vérifier si le code PIN saisi est correct.
— TESTPIN OK (S→C) : La vérification du code PIN est validée.
68 CHAPITRE 7. LA PROGRAMMATION RÉSEAU
Toute opération doit être précédée d’une vérification du code PIN. Les exercices suivants per-
mettront d’effectuer cela en scindant le travail en différentes sous-tâches. Chaque tâche fera l’objet
d’un nouveau programme.
1. Écrivez un programme permettant de créer sur le serveur une base de données SQLite3 nom-
mée banque.db et de créer la structure de table adaptée au stockage des données. Importez
le contenu des fichiers CSV dans cette base.
7.7. EXERCICES 69
70 CHAPITRE 7. LA PROGRAMMATION RÉSEAU
Programme distributeur :
À présent, nous sommes capables de concevoir des programmes très complexes pouvant effectuer
plusieurs opérations différentes. Nos programmes comportent un très grand nombre d’instructions. Il
est temps à présent d’introduire un nouveau paradigme de programmation permettant de structurer
nos programmes : la programmation orientée objet. Un objet est une structure de données
comportant ses propres variables et ses propres fonctions.
Tout au long de ce cours, nous avons utilisé différents objets Python. On peut citer par exemple les
listes, contenant elles-mêmes différentes variables (les éléments qu’elles contiennent) et différentes
fonctions propres (len, sort, . . .) qui agissent sur les listes en question.
Dans ce chapitre et le suivant, nous allons modéliser nos propres objets et les mettre en œuvre
en Python. Pour la modélisation, nous allons utiliser la représentation UML, largement utilisée en
génie logiciel.
La représentation UML représente une classe par un rectangle divisé horizontalement en trois
parties dont le premier tiers renseigne le nom de la classe, le second décrit les variables de celle-ci
et le troisième tiers liste les méthodes de la classe.
73
74 CHAPITRE 8. MODÉLISATION POUR LA PROGRAMMATION ORIENTÉE OBJET
Pour illustrer le concept d’objet, nous allons prendre pour exemple la modélisation d’une personne.
Cette personne a un nom, un prénom, une date de naissance et un lieu de résidence. La classe
comporte également la méthode demenager qui permet de changer de lieu de résidence, ainsi que
la méthode calculerAge retournant l’âge sous forme d’un entier. Nous allons modéliser cela sous la
forme d’une classe : (fig. 8.1).
Personne
nom
prenom
dateDeNaissance
lieuDeResidence
demenager(nouveauLieuDeResidence) : void
calculerAge() : int
Il existe en programmation orientée objet une méthode que l’on retrouve dans tous les objets, à
savoir le constructeur. Cette méthode spéciale exécutée lors de l’instanciation de la classe permet
de créer l’objet en créant les variables que contient l’objet, en définissant leur valeur initiale ou
en effectuant certaines opérations. De manière analogue, il existe le destructeur appelé lors de la
destruction de l’objet.
8.2 L’héritage
Une classe, que nous nommerons ici classe fille peut récupérer les variables et les méthodes
d’une classe mère. On parle ici d’héritage. L’intérêt de cette opération est de partager des variables
et des méthodes communes à différentes classes. Une classe fille peut alors ajouter des éléments
pour compléter l’héritage de la classe mère ou peut écraser certaines méthodes ou variables avec
son contenu propre.
On parle d’héritage simple dans le cas où une classe fille a recours à une seule classe mère. Par
extension, on parle d’héritage multiple si une classe fille hérite des attributs de plusieurs classes
mères.
Nous allons illustrer ce mécanisme avec l’exemple de la classe Chien et la classe Poule qui héritent
tous deux de la classe Animaux (fig. 8.2). La flèche terminée par un triangle indique l’héritage.
Animaux
nom
nombrePattes
position
avancer(nombresPas) : str
Chien Poule
nombrePattes = 4 nombrePattes = 2
Pour illustrer l’héritage multiple, nous allons prendre l’exemple d’une imprimante multifonction
permettant à la fois de scanner et d’imprimer (fig. 8.3) (nous considérons que la photocopie est une
combinaison des deux opérations précédentes) .
Imprimante
Scanner
vitesseImpression
resolutionScanner
couleur
vitesseScanner
resolutionImpression
scanner() : void
imprimer() : void
Multifonction
photocopier() : void
8.3 L’encapsulation
Le principe d’encapsulation est un des concepts clés de la programmation objet. Cette technique
permet de regrouper des données au sein d’une classe et de pouvoir les lire et les manipuler par le
biais de méthodes qui forment une interface pour les éléments environnant l’objet. De ce fait, les
variables et les méthodes contenues au sein d’une classe peuvent être placées dans trois niveaux de
visibilité en fonction de la portée que vous souhaitez :
76 CHAPITRE 8. MODÉLISATION POUR LA PROGRAMMATION ORIENTÉE OBJET
Protégé Les attributs sont accessibles uniquement à la classe et les classes filles.
Pour respecter le principe fondamental de l’encapsulation, toutes les variables doivent être privées
et ne sont accessibles qu’à travers des méthodes conçues pour les modifier qu’après les avoir vérifiées
ou les retourner formatées. Cela se représente dans un diagramme UML par un caractère précédant
le nom de l’attribut ou de la méthode tel que décrit dans le tableau suivant (table 8.1).
Caractère Rôle
+ Accès public
# Accès protégé
- Accès privé
Nous allons illustrer cela avec notre exemple précédent de classe Personnes (fig. 8.4).
Personne
-nom
-prenom
-dateDeNaissance
-lieuDeResidence
+demenager(nouveauLieuDeResidence) : void
+calculerAge() : int
8.4 L’association
Enfin, il est naturellement possible d’utiliser certains objets dans les variables d’autres objets.
On modélise l’association entre les classes par un trait (fig. 8.5) et on fait figurer le type de l’objet
en vis-à-vis du nom de la variable, séparés par deux points. On peut faire figurer une association
monodirectionnelle avec une flèche.
8.5. L’AGRÉGATION ET LA COMPOSITION 77
Personne
-nom
Societe
-prenom
-dateDeNaissance -nom
-lieuDeResidence -raisonSociale
-employeur : Societe -employes
+demenager(nouveauLieuDeResidence) : void
+calculerAge() : int
L’agrégation et la composition désignent le fait qu’un objet soit composé d’autres objets. La
composition entraîne l’appartenance du sous-objet à l’objet alors que l’agrégation non. Nous allons
illustrer par exemple le cas d’une université composée de départements qui agrègent des profes-
seurs. Lors de la destruction de l’université, les départements sont détruits, mais pas les professeurs.
L’agrégation est représentée par un lien terminé par un losange vide (♦) et la composition est un
lien terminé par un losange plein (). Nous allons représenter notre université par un diagramme
UML (fig. 8.6).
Professeur
Departement
Universite -nom
-nom
-prenom
-nom -batiment
-dateDeNaissance
+demenager(nouveauBatiment) : void
+calculerAge() : int
8.6 Exercices
Nous avons vu, dans le chapitre précédent, le concept et la modélisation des objets dans la
programmation. Il est temps à présent d’implémenter les objets sous la forme de code. Python
est un langage orienté objet. En effet, l’intégralité des types de données que nous avons manipulés
jusqu’alors sont des objets. Il est temps à présent de mettre en œuvre nos connaissances en matière de
programmation orientée objet pour simplifier la structure de nos programmes devenus très complexes.
Ce nouveau paradigme nous permettra dans le chapitre suivant l’utilisation des interfaces graphiques.
Personne
nom
prenom
lieuDeResidence
demenager(nouveauLieuDeResidence) : void
Voici le code :
1 c l a s s Personne ( o b j e c t ) :
2 d e f __init__ ( s e l f ) :
3 s e l f . nom = " D u b o i s "
4 s e l f . prenom = " P a u l "
5 s e l f . l i e u D e R e s i d e n c e = " Le Havre "
6 d e f demenager ( s e l f , n o u v e a u L i e u D e R e s i d e n c e ) :
7 s e l f . lieuDeResidence = nouveauLieuDeResidence
79
80 CHAPITRE 9. LA PROGRAMMATION ORIENTÉE OBJET
Chaque classe est identifiée à partir d’un nom que vous donnez. Ce nom est à choisir afin qu’il
respecte les consignes suivantes :
— Le nom de la classe doit être court, mais indiquer son contenu pour faciliter la lecture du
code.
— Ne doit pas être un nom réservé (table 1.2).
— Ne doit comporter que des lettres (a → z et A → Z), des chiffres (0 → 9) et le caractère _
(underscore). Les autres symboles sont interdits.
— Python est sensible à la casse, c’est-à-dire que les majuscules et minuscules sont distinguées
(exemple : livre, Livre et LIVRE sont des variables différentes).
— Il est vivement recommandé de nommer les variables en minuscule, commencer les mots
avec une majuscule pour plus de lisibilité (exemple : CarteAJouer). Dans ce cours, cette
convention de nommage sera à appliquer.
On observe l’apparition du mot self au début des variables qui indique que l’on travaille sur
l’instance de la classe. Voici un petit tableau présentant la syntaxe des noms de variables dans les
classes (table 9.1).
Il est également possible de protéger une méthode en la faisant précéder du double symbole
souligné (__). Cette méthode ne sera accessible uniquement à l’intérieur de la classe.
Une variable privée peut cependant être lue et modifiée via des méthodes spécifiques nommées
accesseurs (lecture) et mutateurs (modification). Cela permet d’effectuer des modifications ou
des contrôles sur les données avant qu’elles soient retournées ou modifiées. Il est vivement recom-
mandé de procéder ainsi plutôt que d’offrir les variables publiquement. L’exemple suivant permet
de mettre en œuvre cette protection des attributs :
1 c l a s s Personne ( o b j e c t ) :
2 d e f __init__ ( s e l f ) :
3 s e l f . __nom = " D u b o i s "
4 s e l f . __prenom = " P a u l "
5 s e l f . _ _ l i e u D e R e s i d e n c e = " Le Havre "
9.2. LES MÉTHODES SPÉCIALES 81
6 d e f __demenager ( s e l f , n o u v e a u L i e u D e R e s i d e n c e ) :
7 s e l f . __lieuDeResidence = nouveauLieuDeResidence
8 d e f demanderNom ( s e l f ) :
9 r e t u r n ( " Je s u i s " + s e l f . __prenom + " " + s e l f . __nom)
Dans l’exemple ci-dessus, la fonction __demenager est accessible uniquement depuis l’objet, alors
que la méthode demanderNom est accessible depuis tout le programme.
8 d e f __str__ ( s e l f ) :
9 r e t u r n ( " Je s u i s " + s e l f . __prenom + " " + s e l f . __nom + " e t j ’
habite à " + s e l f . __lieuDeResidence )
10 p e r s o n n e 1 = P e r s o n n e ( " Dupont " , " C l a r a " , " L i l l e " )
11 p e r s o n n e 2 = P e r s o n n e ( " M a r t i n " , " J u l i e " , "Bé z i e r s " )
12 p r i n t ( p e r s o n n e 1 ) # " Je s u i s C l a r a Dupont e t j ’ h a b i t e à L i l l e "
13 p r i n t ( p e r s o n n e 2 ) # " Je s u i s J u l i e M a r t i n e t j ’ h a b i t e à Bé z i e r s "
Il est également possible de définir des méthodes spéciales permettant de comparer les objets avec
les opérateurs de comparaison que nous avons vus précédemment (table 2.1). On appelle cela la
comparaison riche. Voici la liste des méthodes spéciales associées aux opérateurs de comparaison
(table 9.2).
Ces méthodes doivent avoir comme argument l’objet avec lequel comparer l’objet actuel. Voici
une implémentation de ces comparateurs riches :
1 c l a s s Personne ( o b j e c t ) :
2 d e f __init__ ( s e l f , nom , prenom , age ) :
3 s e l f . __nom = nom
4 s e l f . __prenom = prenom
5 s e l f . __age = age
6 d e f getPrenom ( s e l f ) :
7 r e t u r n ( s e l f . __prenom )
8 d e f getAge ( s e l f ) :
9 r e t u r n ( s e l f . __age )
10 d e f __lt__ ( s e l f , a u t r e P e r s o n n e ) :
11 r e t u r n ( s e l f . __age < a u t r e P e r s o n n e . getAge ( ) )
12 p e r s o n n e 1 = P e r s o n n e ( " Dupont " , " C l a r a " , 2 4)
13 p e r s o n n e 2 = P e r s o n n e ( " M a r t i n " , " J u l i e " , 27 )
14 i f p e r s o n n e 1 < p e r s o n n e 2 : # U t i l i s e p e r s o n n e 1 . __lt__ ( p e r s o n n e 2 )
15 p r i n t ( p e r s o n n e 1 . getPrenom ( ) + " e s t l a p l u s j e u n e . " )
16 e l s e :
17 p r i n t ( p e r s o n n e 2 . getPrenom ( ) + " e s t l a p l u s j e u n e . " )
9.3. L’HÉRITAGE 83
9.3 L’héritage
L’héritage se matérialise par la modification de l’argument lors de la définition de la classe. Nous
allons reprendre le modèle UML des animaux vus précédemment (fig. 9.2).
Animaux
nom
nombrePattes
position
avancer(nombresPas) : str
Chien Poule
nombrePattes = 4 nombrePattes = 2
9.4 Exercices
N’oubliez pas le shebang et commentez si nécessaire.
Nous allons écrire un programme permettant à un utilisateur de jouer au jeu du Yahtzee contre
des joueurs pilotés par l’ordinateur.
Le Yahtzee est un jeu de société se jouant à l’aide de cinq dés à six faces et où le but est d’obtenir
un maximum de points.
Lorsque c’est au tour d’un joueur de jouer, celui-ci doit essayer de réaliser des combinaisons
détaillées ci-dessous à l’aide des cinq dés qu’il peut jeter trois fois par tour. Le joueur est libre quant
au nombre de dés à jeter sauf pour le premier jet où il doit jeter tous les dés.
À la fin du tour, le joueur doit inscrire le score obtenu dans la grille des scores (table 9.3), même
si le joueur doit inscrire un score nul. Chaque ligne de la grille est utilisable qu’une seule fois, il n’est
pas possible de remplacer le score inscrit dans une ligne.
Une partie se compose de 13 tours afin de remplir les 13 lignes de la grille des scores. La grille
des scores se divise en deux parties, la grille supérieure et la grille inférieure.
Nous modéliserons la partie, les joueurs, le plateau de jeu et les dés sous forme d’objets. On fera la
distinction entre les joueurs humains et ordinateurs par deux classes partageant la même classe mère.
86 CHAPITRE 9. LA PROGRAMMATION ORIENTÉE OBJET
Nous avons vu jusqu’à présent comment concevoir des applications en mode console, à savoir,
n’utilisant que le mode texte comme interface avec l’utilisateur. Or, la plupart des applications
utilisées par le grand public offrent une interface graphique : une fenêtre comportant des boutons,
des zones de texte, des cases à cocher, . . . Il est temps pour nous d’aborder comment parer nos
applications d’une interface graphique et ainsi rendre leur utilisation beaucoup plus aisée.
Il existe plusieurs bibliothèques graphiques en Python telles que Tkinter qui offre un choix limité
d’éléments graphiques et son aspect est assez austère. Nous allons utiliser la librairie PySide2 depuis
le module éponyme qui offre la plupart des composants courants et qui est assez simple d’utilisation.
De plus, elle s’adapte au thème configuré sur le système d’exploitation.
87
88 CHAPITRE 10. LES INTERFACES GRAPHIQUES
15 r e t u r n ( motDePasse )
Notre interface permet de choisir quels jeux de caractères utiliser pour notre mot de passe à
l’aide des cases à cocher. La glissière permet de faire varier la taille du mot de passe. Enfin, après
avoir cliqué sur le bouton Générer, le mot de passe apparaît dans la zone de texte. Le bouton
Vers le presse-papier copie le mot de passe généré dans le presse-papier et le bouton Quitter ferme
l’application.
Nous allons donc écrire une classe correspondant à notre fenêtre en héritant la classe QDialog et
y décrire l’ensemble des widgets comme des attributs de la classe dans le constructeur :
1 import sys
2 from P y S i d e 2 i m p o r t QtCore , QtGui , QtWidgets
3 c l a s s MaFenetre ( QtWidgets . QDialog ) :
4 d e f __init__ ( s e l f , p a r e n t=None ) :
5 QtWidgets . QDialog . __init__ ( s e l f , p a r e n t )
6 # Les c a s e s à cocher
7 s e l f . _ _ c a s e M i n u s c u l e s = QtWidgets . QCheckBox ( " M i n u s c u l e s " )
8 s e l f . _ _ c a s e M a j u s c u l e s = QtWidgets . QCheckBox ( " M a j u s c u l e s " )
10.1. APPLICATION : UN GÉNÉRATEUR DE MOT DE PASSE 89
Nous allons à présent aborder le placement des widgets dans la boîte de dialogue. PySide nous
propose plusieurs méthodes pour placer les widgets. La solution la plus simple est le placement sur
une grille à l’aide de la classe QGridLayout : chaque widget occupe une case dans une grille. Il est
cependant possible de faire en sorte qu’un widget occupe plusieurs lignes ou colonnes.
Voici notre maquette d’interface dont les widgets ont été répartis sur une grille (fig. 10.2).
Pour implémenter cela, nous allons créer un objet de la classe QGridLayout, puis ajouter les
widgets créés précédemment avec la méthode addWidget(widget, ligne, colonne) avec ligne
et colonne, le numéro de la ligne et de la colonne souhaitées. Enfin, nous définirons le layout comme
étant l’élément central de la fenêtre avec self.setLayout(layout).
Nous allons terminer la préparation de notre fenêtre en modifiant le titre de la boîte de dialogue
avec la méthode self.setWindowTitle(titre). Nous allons également définir le minimum et le
maximum de la glissière avec respectivement les méthodes setMinimum et setMaximum. Nous allons
cocher par défaut la case minuscules et chiffres avec la méthode setChecked. Nous ajoutons les
lignes suivantes à notre constructeur :
Nous allons enfin ajouter une icône à notre application pour que celle-ci soit reconnaissable dans la
barre des tâches. Nous ajoutons les trois lignes suivantes au constructeur de notre boîte de dialogue :
Pour exécuter notre fenêtre, on écrit les lignes suivantes dans le programme principal qui per-
mettent de créer une application Qt en fournissant les arguments de la ligne de commande (ligne
1), instancie notre fenêtre (ligne 2) et l’affiche (ligne 3) :
1 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
2 d i a l o g = MaFenetre ( )
3 d i a l o g . exec_ ( )
32 l a y o u t . addWidget ( s e l f . __boutonCopier , 3 , 1 )
33 l a y o u t . addWidget ( s e l f . __boutonGenerer , 3 , 2 )
34 s e l f . setLayout ( layout )
35 s e l f . s e t W i n d o w T i t l e ( "Gé n é r a t e u r de mot de p a s s e " )
36 i c o n e = QtGui . QIcon ( )
37 i c o n e . addPixmap ( QtGui . QPixmap ( " c a d e n a s . s v g " ) )
38 s e l f . setWindowIcon ( i c o n e )
39 s e l f . _ _ c a s e M i n u s c u l e s . s e t C h e c k e d ( True )
40 s e l f . _ _ c a s e C h i f f r e s . s e t C h e c k e d ( True )
41 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
42 d i a l o g = MaFenetre ( )
43 d i a l o g . exec_ ( )
Chaque widget de la fenêtre produit des signaux lorsqu’on l’utilise. Chaque signal peut être relié
à un slot avec la méthode connect en fournissant en argument quelle fonction appeler lors de la
réception du signal.
Pour illustrer cela, nous allons créer une méthode à notre objet MaFenetre, nommée quitter,
et contenant la ligne self.accept() qui ferme la boîte de dialogue. Nous allons connecter le signal
clicked (généré quand le bouton est cliqué) émis par le bouton Quitter à cette fonction :
1 c l a s s MaFenetre ( QtWidgets . QDialog ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 # ...
4 s e l f . __boutonQuitter . c l i c k e d . connect ( s e l f . q u i t t e r )
5 def q u i t t e r ( s e l f ) :
6 s e l f . accept ()
10.2. LES SIGNAUX 93
Nous allons faire de même pour les boutons Vers le presse-papier et Générer. La copie vers le
presse-papier nécessite la création d’un objet QtGui.QApplication.clipboard() et on y affecte,
avec la méthode setText(texte) le contenu du champ de texte, lu avec la méthode text().
De manière analogue, nous allons créer une fonction generer permettant d’appeler notre fonction
genererMotDePasse en lui fournissant comme arguments la taille souhaitée, lue depuis la glissière
avec la méthode value() et en choisissant les caractères à partir des cases à cocher avec la méthode
isChecked() qui retourne True lorsqu’elles sont cochées. Enfin, la valeur retournée par la fonction
sera définie comme texte du champ de texte avec la méthode setText(texte).
Nous allons améliorer notre programme en modifiant la valeur du label Taille du mot de passe :
en ajoutant la valeur actuelle de la glissière. Pour cela, nous modifions la ligne créant notre label
et ajouter une fonction déclenchée par la modification de la valeur de la glissière, à savoir le signal
valueChanged().
1 c l a s s MaFenetre ( QtWidgets . QDialog ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 # ...
4 s e l f . _ _ l a b e l T a i l l e = QtWidgets . QLabel ( " T a i l l e du mot de p a s s e
: " + str ( s e l f . _ _ g l i s s i e r e T a i l l e . value () ) )
5 # ...
6 s e l f . _ _ g l i s s i e r e T a i l l e . valueChanged . connect ( s e l f .
changerTailleMotDePasse )
94 CHAPITRE 10. LES INTERFACES GRAPHIQUES
7 def changerTailleMotDePasse ( s e l f ) :
8 s e l f . _ _ l a b e l T a i l l e . s e t T e x t ( " T a i l l e du mot de p a s s e : " + s t r (
s e l f . _ _ g l i s s i e r e T a i l l e . value () ) )
1 import sys
2 from P y S i d e 2 i m p o r t QtCore , QtGui , QtWidgets
3 from random i m p o r t c h o i c e
4 d e f g e n e r e r M o t D e P a s s e ( t a i l l e M o t D e P a s s e =8, m i n u s c u l e s=True ,
m a j u s c u l e s=True , c h i f f r e s =True , s y m b o l e s=True ) :
5 caracteres = ""
6 i f minuscules :
7 c a r a c t e r e s += " a b c d e f g h i j k l m n o p q r s t u v w x y z "
8 i f majuscules :
9 c a r a c t e r e s += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
10 if chiffres :
11 c a r a c t e r e s += " 0123456789 "
12 i f symboles :
13 c a r a c t e r e s += " &~#{([−|_\^@)=+$ ] } ∗ % ! / : . ; ? , "
14 motDePasse = " "
15 f o r i in range ( tailleMotDePasse ) :
16 motDePasse += c h o i c e ( c a r a c t e r e s )
17 r e t u r n ( motDePasse )
18 c l a s s MaFenetre ( QtWidgets . QDialog ) :
19 d e f __init__ ( s e l f , p a r e n t=None ) :
20 QtWidgets . QDialog . __init__ ( s e l f , p a r e n t )
21 # Les c a s e s à cocher
22 s e l f . _ _ c a s e M i n u s c u l e s = QtWidgets . QCheckBox ( " M i n u s c u l e s " )
23 s e l f . _ _ c a s e M a j u s c u l e s = QtWidgets . QCheckBox ( " M a j u s c u l e s " )
24 s e l f . _ _ c a s e C h i f f r e s = QtWidgets . QCheckBox ( " C h i f f r e s " )
25 s e l f . __caseSymboles = QtWidgets . QCheckBox ( " Symbol es " )
26 # Les boutons
27 s e l f . _ _ b o u t o n Q u i t t e r = QtWidgets . QPushButton ( " Q u i t t e r " )
28 s e l f . __boutonCopier = QtWidgets . QPushButton ( " V e r s l e p r e s s e −
papier ")
29 s e l f . __boutonGenerer = QtWidgets . QPushButton ( "Gé n é r e r " )
30 # Le champ de t e x t e
31 s e l f . __champTexte = QtWidgets . Q L i n e E d i t ( " " )
32 # La g l i s s i è r e
33 s e l f . _ _ g l i s s i e r e T a i l l e = QtWidgets . Q S l i d e r ( QtCore . Qt .
Horizontal )
34 s e l f . _ _ g l i s s i e r e T a i l l e . setMinimum ( 8 )
35 s e l f . _ _ g l i s s i e r e T a i l l e . setMaximum ( 3 0 )
10.2. LES SIGNAUX 95
36 # Le l a b e l
37 s e l f . _ _ l a b e l T a i l l e = QtWidgets . QLabel ( " T a i l l e du mot de p a s s e
: " + str ( s e l f . _ _ g l i s s i e r e T a i l l e . value () ) )
38 l a y o u t = QtWidgets . Q G r i d L a y o u t ( )
39 l a y o u t . addWidget ( s e l f . _ _ c a s e M a j u s c u l e s , 0 , 0 )
40 l a y o u t . addWidget ( s e l f . _ _ l a b e l T a i l l e , 0 , 1 )
41 l a y o u t . addWidget ( s e l f . _ _ c a s e M i n u s c u l e s , 0 , 2 )
42 l a y o u t . addWidget ( s e l f . _ _ c a s e C h i f f r e s , 1 , 0 )
43 l a y o u t . addWidget ( s e l f . _ _ g l i s s i e r e T a i l l e , 1 , 1 )
44 l a y o u t . addWidget ( s e l f . __caseSymboles , 1 , 2 )
45 l a y o u t . addWidget ( s e l f . __champTexte , 2 , 1 )
46 l a y o u t . addWidget ( s e l f . _ _ b o u t o n Q u i t t e r , 3 , 0 )
47 l a y o u t . addWidget ( s e l f . __boutonCopier , 3 , 1 )
48 l a y o u t . addWidget ( s e l f . __boutonGenerer , 3 , 2 )
49 s e l f . setLayout ( layout )
50 s e l f . s e t W i n d o w T i t l e ( "Gé n é r a t e u r de mot de p a s s e " )
51 i c o n e = QtGui . QIcon ( )
52 i c o n e . addPixmap ( QtGui . QPixmap ( " c a d e n a s . s v g " ) )
53 s e l f . setWindowIcon ( i c o n e )
54 s e l f . _ _ c a s e M i n u s c u l e s . s e t C h e c k e d ( True )
55 s e l f . _ _ c a s e C h i f f r e s . s e t C h e c k e d ( True )
56 s e l f . __boutonQuitter . c l i c k e d . connect ( s e l f . q u i t t e r )
57 s e l f . __boutonCopier . c l i c k e d . c o n n e c t ( s e l f . c o p i e r )
58 s e l f . __boutonGenerer . c l i c k e d . c o n n e c t ( s e l f . g e n e r e r )
59 s e l f . _ _ g l i s s i e r e T a i l l e . valueChanged . connect ( s e l f .
changerTailleMotDePasse )
60 def q u i t t e r ( s e l f ) :
61 s e l f . accept ()
62 def copier ( s e l f ) :
63 p r e s s e P a p i e r = QtWidgets . Q A p p l i c a t i o n . c l i p b o a r d ( )
64 p r e s s e P a p i e r . s e t T e x t ( s e l f . __champTexte . t e x t ( ) )
65 def generer ( s e l f ) :
66 tailleMotDePasse = s e l f . _ _ g l i s s i e r e T a i l l e . value ()
67 minuscules = s e l f . __caseMinuscules . isChecked ()
68 majuscules = s e l f . __caseMajuscules . isChecked ()
69 c h i f f r e s = s e l f . __caseChiffres . isChecked ()
70 s y m b o l e s = s e l f . __caseSymboles . i s C h e c k e d ( )
71 s e l f . __champTexte . s e t T e x t ( g e n e r e r M o t D e P a s s e ( t a i l l e M o t D e P a s s e ,
minuscules , majuscules , c h i f f r e s , symboles ) )
72 def changerTailleMotDePasse ( s e l f ) :
73 s e l f . _ _ l a b e l T a i l l e . s e t T e x t ( " T a i l l e du mot de p a s s e : " + s t r (
s e l f . _ _ g l i s s i e r e T a i l l e . value () ) )
74 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
96 CHAPITRE 10. LES INTERFACES GRAPHIQUES
75 d i a l o g = MaFenetre ( )
76 d i a l o g . exec_ ( )
10.3.1 Présentation
L’ensemble des widgets présentés ici héritent de la classe QWidget qui offre une méthode
setEnabled, qui permet d’activer ou de désactiver le widget. Nous allons découvrir dans cette
section plusieurs widgets courants proposés par PySide.
Méthode Description
text() Retourne le texte contenu dans le champ de texte.
setText(texte) Modifie le contenu du champ de texte par le texte fourni en
argument.
clear() Efface le contenu du champ de texte.
setMaxLength(taille) Définit la taille maximale du champ de texte.
maxLength(taille) Retourne la taille maximale du champ de texte.
copy() Copie le contenu du champ de texte dans le presse-papier.
paste() Colle le contenu du presse-papier dans le champ de texte.
setEchoMode(mode) Modifie l’affichage du contenu du champ de texte sans modi-
fier son contenu :
— QLineEdit.Normal : Affiche les caractères normale-
ment (par défaut).
— QLineEdit.NoEcho : Rien n’est affiché.
— QLineEdit.Password : Affiche des étoiles à la place
des caractères (pour les mots de passe)
— QLineEdit.PasswordEchoOnEdit : Affiche les carac-
tères normalement tant que le champ est sélectionné.
Sinon, affiche des étoiles.
Méthode Description
setInputMask(masque) Permet de configurer le format de données attendu avec une
chaîne de caractères. Par exemple :
— 000.000.000.000 : Adresse IPv4
— HH:HH:HH:HH:HH:HH : Adresse MAC
— 00-00-0000 : Date au format JJ-MM-AAAA.
Il est possible de rendre le masque visible en lui ajoutant
";" suivi d’un caractère de remplacement. Par exemple,
"00-00-0000;_" affichera "__-__-____" tant qu’il ne sera
pas rempli.
Signal Déclencheur
textChanged Lorsque le texte change (par l’utilisateur ou par le pro-
gramme).
textEdited Lorsque le texte est changé par l’utilisateur.
cursorPositionChanged Lorsque le curseur est déplacé.
returnPressed Lorsque la touche Entrée est pressée.
editingFinished Lorsque le champ perd le focus ou la touche Entrée est
pressée.
Méthode Description
setIcon(icone) Permet d’ajouter une icône avec une instance de la classe
QtGui.QIcon au bouton.
setShortcut(raccourci) Associe au bouton un raccourci clavier sous la forme d’une
chaîne de caractères (exemple : CTRL+C).
setCheckable() Permet de rendre le bouton bistable (il maintient l’état après
le clic). Les QRadioButton et QCheckBox sont bistables par
défaut.
setChecked() Permet de valider un bouton.
isChecked() Retourne l’état du bouton.
98 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Signal Déclencheur
clicked Lorsque le bouton est cliqué.
pressed Lorsque le bouton est appuyé.
released Lorsque le bouton est relâché.
toogled Lorsque le bouton change d’état comme par exemple les bou-
tons de barre d’outils.
Méthode Description
addItem(chaine) Permet d’ajouter une chaîne de caractères (avec ou sans
addItem(icone, chaine) icône) à la liste de choix.
addItems(liste) Permet d’ajouter une liste de chaîne de caractères à la liste de
choix.
currentIndex() Retourne l’index de l’élément actuellement sélectionné.
currentText() Retourne la chaîne de caractères actuellement sélectionnée.
setEditable() Permet de modifier ou non les éléments de la boîte de sélec-
tion. Par défaut, cela n’est pas possible.
10.3. LES WIDGETS COURANTS PYSIDE 99
Méthode Description
insertItem(l, chaine) Permet d’ajouter un ou plusieurs éléments pendant
insertItems(l, liste) l’exécution du programme à l’index l.
insertSeparator() Permet de grouper les éléments en ajoutant un séparateur
entre ceux-ci.
clear() Efface les éléments contenus.
Signal Déclencheur
activated Lorsque l’utilisateur interagit avec.
currentIndexChanged Lorsque l’élément sélectionné change (par le programme ou
l’utilisateur). Retourne l’index de l’élément sélectionné.
highlighted Retourne l’index de l’élément surligné.
editTextChanged Lorsque l’utilisateur modifie le contenu de la boîte de dialogue.
Méthode Description
setMinimum(minimum)
Définissent le minimum et le maximum autorisés par le
setMaximum(maximum)
champ.
setRange(min, max)
setSingleStep Fixe le pas d’incrémentation.
setSuffix(chaine) Ajoutent un suffixe ou un préfixe au champ pour plus de
setPrefix(chaine) lisibilité (exemple : €, £, litres, km, . . .).
setValue(valeur) Définit la valeur du champ.
value() Retourne la valeur du champ.
setDecimals(nbDecimales) Pour QDoubleSpinBox. Permet de définir le nombre de déci-
males à l’affichage.
Ces deux champs numériques offrent un seul signal : valueChanged qui est émit quand l’utilisateur
change la valeur contenue. La valeur retournée est la valeur du champ. Pour QDoubleSpinBox, la
chaîne de caractères est codée en fonction de la langue (en France, on utilise une virgule (,) comme
séparateur de décimale).
100 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Méthode Description
date()
Retournent la valeur du champ sous la forme d’un objet
time()
QDate, QTime ou QDateTime.
dateTime()
setDate()
On remplit le champ avec les objets QDate, QTime ou
setTime()
QDateTime.
setDateTime()
setMinimumDate()
Définissent le minimum du champ avec les objets QDate,
setMinimumTime()
QTime ou QDateTime.
setMinimumDateTime()
setMaximumDate()
Définissent le maximum du champ avec les objets QDate,
setMaximumTime()
QTime ou QDateTime.
setMaximumDateTime()
setCalendarPopup() Permet d’afficher un calendrier pour les objets manipulant des
dates.
Signal Déclencheur
dateChanged
timeChanged Déclenchés lors de la modification de la valeur.
dateTimeChanged
Méthode Description
toPlainText() Retourne le texte contenu dans le champ de texte.
setText(texte) Modifie le texte du champ par celui en argument.
toHtml() Retourne le code HTML contenu dans le champ de texte.
10.3. LES WIDGETS COURANTS PYSIDE 101
Méthode Description
setHtml(texte) Modifie le contenu du champ de texte par le code HTML
fourni en argument.
clear() Efface le contenu du champ de texte.
copy() Copie le contenu du champ de texte dans le presse-papier.
paste() Colle le contenu du presse-papier dans le champ de texte.
undo() Annule la dernière opération.
redo() Refait la dernière opération annulée.
Signal Déclencheur
textChanged Lorsque le texte change (par l’utilisateur ou par le pro-
gramme).
cursorPositionChanged Lorsque le curseur s’est déplacé.
Méthode Description
addTab(widget, nom) Permet d’ajouter un onglet contenant un widget et dont le
nom et le widget sont passés en argument.
insertTab(widget, nom) Permet d’ajouter un onglet contenant un widget et dont le
nom et le widget sont passés en argument pendant l’exécution
du programme.
tabPosition() Retourne l’indice de l’onglet actuellement sélectionné.
Le signal currentChanged est émis lorsque l’utilisateur change d’onglet. Voici un exemple de
mise en œuvre de la boîte à onglets (fig. 10.4).
6 # L e s champs
7 s e l f . __champTexteNomAuteur = QtWidgets . Q L i n e E d i t ( " " )
8 s e l f . __champTextePrenomAuteur = QtWidgets . Q L i n e E d i t ( " " )
9 s e l f . __champDateNaissanceAuteur = QtWidgets . QDateEdit ( )
10 s e l f . __champDateNaissanceAuteur . s e t C a l e n d a r P o p u p ( True )
11 s e l f . _ _ c h a m p T e x t e T i t r e L i v r e = QtWidgets . Q L i n e E d i t ( " " )
12 s e l f . _ _ c h a m p D a t e P u b l i c a t i o n = QtWidgets . QDateEdit ( )
13 s e l f . _ _ c h a m p D a t e P u b l i c a t i o n . s e t C a l e n d a r P o p u p ( True )
14 # Les widgets
15 s e l f . __widgetAuteur = QtWidgets . QWidget ( )
16 s e l f . _ _ w i d g e t L i v r e = QtWidgets . QWidget ( )
17 # Les l a y o u t s des o n g l e t s
18 s e l f . _ _ l a y o u t A u t e u r = QtWidgets . QFormLayout ( )
19 s e l f . _ _ l a y o u t A u t e u r . addRow ( "Nom : " , s e l f .
__champTexteNomAuteur )
20 s e l f . _ _ l a y o u t A u t e u r . addRow ( " Pr énom : " , s e l f .
__champTextePrenomAuteur )
21 s e l f . _ _ l a y o u t A u t e u r . addRow ( " Date de n a i s s a n c e : " , s e l f .
__champDateNaissanceAuteur )
22 s e l f . __widgetAuteur . s e t L a y o u t ( s e l f . _ _ l a y o u t A u t e u r )
23 s e l f . _ _ l a y o u t L i v r e = QtWidgets . QFormLayout ( )
24 s e l f . _ _ l a y o u t L i v r e . addRow ( " T i t r e : " , s e l f .
__champTexteTitreLivre )
25 s e l f . _ _ l a y o u t L i v r e . addRow ( " Date de p u b l i c a t i o n : " , s e l f .
__champDatePublication )
26 s e l f . __widgetLivre . setLayout ( s e l f . __layoutLivre )
27 # La bo î t e à o n g l e t s
28 s e l f . __tabWidget = QtWidgets . QTabWidget ( )
29 s e l f . __tabWidget . addTab ( s e l f . __widgetAuteur , " A u t e u r " )
30 s e l f . __tabWidget . addTab ( s e l f . _ _ w i d g e t L i v r e , " L i v r e " )
31 # Le l a y o u t f i n a l
32 s e l f . __mainLayout = QtWidgets . QVBoxLayout ( )
33 s e l f . __mainLayout . addWidget ( s e l f . __tabWidget )
34 s e l f . s e t L a y o u t ( s e l f . __mainLayout )
10.3. LES WIDGETS COURANTS PYSIDE 103
35 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
36 d i a l o g = D i a l o g ( )
37 d i a l o g . exec_ ( )
Méthode Description
setLayout(layout) Définit le layout passé en argument comme le layout utilisé
pour cette instance.
setChecked(bool) Permet de créer une boîte de regroupement optionnelle.
isChecked() Pour les boîtes de regroupement optionnelles, retourne si le
groupe a été coché.
Méthode Description
addWidget(widget) Ajoute un widget aux panneaux.
setStretchFactor(index, Permet de définir un cœfficient de la taille occupée par chaque
entier) widget.
setOrientation(arg) Permet de modifier l’orientation du panneau séparé. Voici les
arguments possibles :
— Qt.Vertical : Empilement vertical (par défaut)
— Qt.Horizontal : Empilement horizontal.
104 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Méthode Description
addItem(chaine) Ajoute un élément à la liste (texte seul).
addItem(item) Ajoute un objet QListWidgetItem à la liste (texte et icône).
insertItem(l, chaine) Permet d’ajouter un ou plusieurs éléments à la position
insertItems(l, liste) pendant l’exécution du programme.
setViewMode(arg) Permet de modifier le mode d’affichage de la liste :
— QtListView.ListMode : Vue en liste (par défaut)
— QtListView.IconMode : Vue en icônes
Signal Déclencheur
currentItemCanged Déclenché lors du changement d’éléments sélectionnés. Re-
tourne l’élément précédemment sélectionné et l’élément nou-
vellement sélectionné.
itemActivated Déclenché lors de la sélection d’un élément. Retourne l’élé-
ment sélectionné.
itemClicked Déclenché lors du clic d’un élément. Retourne l’élément cliqué.
itemDoubleClicked Déclenché lors du double-clic d’un élément. Retourne l’élé-
ment double-cliqué.
Méthode Description
setItem(ligne, colonne, Définit la cellule spécifiée par sa ligne et sa co-
item) lonne. L’item passé en argument est un objet
QTableWidgetItem(chaine).
10.3. LES WIDGETS COURANTS PYSIDE 105
Méthode Description
setHorizontalHeaderLabelsModifie les en-têtes des colonnes de la table.
(liste)
setVerticalHeaderLabels Modifie les en-têtes des lignes de la table.
(liste)
setRowCount(nombre) Définit le nombre de lignes passées en argument.
setColumnCount(nombre) Définit le nombre de colonnes passées en argument.
rowCount() Retourne le nombre de lignes de la table.
columnCount() Retourne le nombre de colonnes de la table.
Signal Déclencheur
currentItemCanged Déclenché lors du changement d’éléments sélectionnés. Re-
tourne l’élément précédemment sélectionné et l’élément nou-
vellement sélectionné.
itemActivated Déclenché lors de la sélection d’un élément. Retourne l’élé-
ment sélectionné.
itemClicked Déclenché lors du clic d’un élément. Retourne l’élément cliqué.
itemDoubleClicked Déclenché lors du double-clic d’un élément. Retourne l’élé-
ment double-cliqué.
currentCellCanged Déclenché lors du changement d’éléments sélectionnés. Re-
tourne les coordonnées de l’élément précédemment sélectionné
et les coordonnées de l’élément nouvellement sélectionné.
cellActivated Déclenché lors de la sélection d’un élément. Retourne les co-
ordonnées de l’élément sélectionné.
cellClicked Déclenché lors du clic d’un élément. Retourne les coordonnées
de l’élément cliqué.
cellDoubleClicked Déclenché lors du double-clic d’un élément. Retourne les co-
ordonnées de l’élément double-cliqué.
Il est possible de représenter les données sous la forme d’un arbre. Chaque élément de l’arbre est
une instance de la classe QtWidgets.QTreeWidgetItem avec en argument la chaîne de caractères
de l’élément. Pour ajouter un élément enfant, on utilise la méthode addChild(item) avec comme
argument l’item enfant implémentant QTreeWidgetItem. On définit l’élément racine de l’arbre avec
la méthode addTopLevelItem(item). Les signaux sont identiques à la classe QListWidget.
106 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Méthode Description
getInt(parent, titre, Demande un entier à l’utilisateur.
message, valeur)
getDouble(parent, Demande un réel à l’utilisateur.
titre, message, valeur)
getItem(parent, titre, Demande un élément parmi la liste à l’utilisateur. Peut être
message, listeValeurs, modifiable si editable=True.
editable)
getText(parent, titre, Demande une chaîne à l’utilisateur. Peut être caché si
message) echo=QtWidgets.QLineEdit.Password.
Méthode Description
selectedColor() Retourne la couleur choisie par l’utilisateur (classe QColor).
setCurrentColor(couleur) Définit la couleur de la boîte de dialogue.
getColor() Ouvre la boîte de dialogue pour choisir la couleur.
Signal Déclencheur
colorSelected Déclenché lors de la sélection d’une couleur. Retourne la cou-
leur sélectionnée.
currentColorChanged Déclenché lors du changement de couleur choisie. Retourne la
couleur sélectionnée.
10.4. LES LAYOUTS 107
Méthode Description
selectedFont() Retourne la fonte choisie par l’utilisateur (classe QFont).
setCurrentFont(fonte) Définit la fonte de la boîte de dialogue.
getFont() Ouvre la boîte de dialogue pour choisir la fonte.
Signal Déclencheur
fontSelected Déclenché lors de la sélection d’une fonte. Retourne la fonte
sélectionnée.
currentFontChanged Déclenché lors du changement de fonte choisie. Retourne la
fonte sélectionnée.
Méthode Description
getExistingDirectory() Permet de sélectionner un répertoire.
getOpenFileName() Permet de sélectionner un fichier à ouvrir.
getOpenFileNames() Permet de sélectionner un ou plusieurs fichiers à ouvrir.
getSaveFileName() Permet de sauvegarder un fichier.
10.4.1 Le placement sur une ligne QHBoxLayout et sur une colonne QVBoxLayout
Ces layouts simplifient la mise en place des widgets en les juxtaposant (verticalement avec
QVBoxLayout et horizontalement avec QHBoxLayout) avec la méthode addWidget(widget). Il est
108 CHAPITRE 10. LES INTERFACES GRAPHIQUES
cependant possible d’ajouter un layout au sein du layout actuel avec la méthode addLayout(layout).
Il est enfin possible d’ajouter un espace élastique qui occupe tout l’espace restant lors du redimen-
sionnement de la fenêtre avec addStretch.
29 s e l f . _ _ l a y o u t P r i n c i p a l = QtWidgets . QVBoxLayout ( )
30 s e l f . _ _ l a y o u t P r i n c i p a l . addLayout ( s e l f . _ _ l a y o u t L i b e l l e )
31 s e l f . _ _ l a y o u t P r i n c i p a l . addLayout ( s e l f . __layoutPrix )
32 s e l f . _ _ l a y o u t P r i n c i p a l . addLayout ( s e l f . __layoutBoutons )
33 s e l f . setLayout ( s e l f . __layoutPrincipal )
34 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
35 d i a l o g = D i a l o g ( )
36 d i a l o g . exec_ ( )
Le layout possède la méthode addRow(chaine, widget) qui crée le label associé aux widgets
avec comme texte la chaîne passée en argument.
1 layout = QtWidgets . Q G r i d L a y o u t ( )
2 layout . addWidget ( w i d g e t 0 , 0 , 0 , 1 , 2 )
3 layout . addWidget ( w i d g e t 1 , 0 , 2 )
4 layout . addWidget ( w i d g e t 2 , 1 , 0 , 2 , 1 )
5 layout . addWidget ( w i d g e t 3 , 1 , 1 )
6 layout . addWidget ( w i d g e t 4 , 1 , 2 ) Widget 0 Widget 1
7 layout . addWidget ( w i d g e t 5 , 2 , 1 ) Widget 3 Widget 4
8 layout . addWidget ( w i d g e t 6 , 2 , 2 ) Widget 2
Widget 5 Widget 6
(a) Code source (b) Rendu
Bloc-notes
Fichier Édition
Nouveau
Ouvrir
Enregistrer
Enregistrer sous
Quitter
Nous allons instancier la classe QMainWindow qui est affichée en appelant la méthode show() ou
la méthode setVisible(bool). Dans cette partie, nous aborderons uniquement la construction de
la fenêtre avec la barre d’outils et de menu.
1 import sys
2 from P y S i d e 2 i m p o r t QtCore , QtGui , QtWidgets
3 c l a s s B l o c N o t e s ( QtWidgets . QMainWindow ) :
4 d e f __init__ ( s e l f , p a r e n t=None ) :
5 QtWidgets . QMainWindow . __init__ ( s e l f , p a r e n t )
6 # La f e n ê t r e s e r a d é c r i t e i c i
7 s e l f . show ( )
8 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
9 f e n e t r e = BlocNotes ()
10 app . exec_ ( )
Nous allons créer la zone de texte centrale et la définir comme widget central de la fenêtre :
1 c l a s s B l o c N o t e s ( QtWidgets . QMainWindow ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 QtWidgets . QMainWindow . __init__ ( s e l f , p a r e n t )
4 s e l f . s e t W i n d o w T i t l e ( " Bloc−n o t e s " )
5 s e l f . __zoneTexte = QtWidgets . QTextEdit ( )
6 s e l f . s e t C e n t r a l W i d g e t ( s e l f . __zoneTexte )
7 # ...
10.5. LES FENÊTRES PRINCIPALES 111
Pour définir un layout comme widget central, créez une instance QtWidgets.QWidget, affectez
votre layout à ce widget avec la méthode setLayout et définissez ce widget comme widget central.
Méthode Description
setStatusTip(chaine) Définit le texte affiché dans la barre d’actions des fenêtres.
setShortcuts(raccourci) Définit le raccourci clavier. L’argument est une instance de la
classe QKeySequence.
Les actions génèrent le signal triggered lorsqu’elles sont activées. Voici les actions utilisées pour
notre application :
— Nouveau
— Ouvrir
— Enregistrer
— Enregistrer sous
— Quitter
— Annuler
— Refaire
— Couper
— Copier
— Coller
1 c l a s s B l o c N o t e s ( QtWidgets . QMainWindow ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 QtWidgets . QMainWindow . __init__ ( s e l f , p a r e n t )
4 # ...
5 s e l f . __actionNew = QtWidgets . QAction ( QtGui . QIcon ( " document−new
. s v g " ) , " Nouveau " , s e l f )
6 s e l f . __actionNew . s e t S h o r t c u t s ( QtGui . QKeySequence . New)
7 s e l f . __actionNew . s e t S t a t u s T i p ( " Nouveau document " )
112 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Nous allons associer les actions aux méthodes créées (non décrites ici) :
1 c l a s s B l o c N o t e s ( QtWidgets . QMainWindow ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 QtWidgets . QMainWindow . __init__ ( s e l f , p a r e n t )
4 # ...
5 s e l f . __actionNew . t r i g g e r e d . c o n n e c t ( s e l f . newDocument )
6 s e l f . __actionOpen . t r i g g e r e d . c o n n e c t ( s e l f . openDocument )
7 s e l f . _ _ a c t i o n S a v e . t r i g g e r e d . c o n n e c t ( s e l f . saveDocument )
8 s e l f . _ _ a c t i o n S a v e A s . t r i g g e r e d . c o n n e c t ( s e l f . saveAsDocument )
9 s e l f . __actionQuit . t r i g g e r e d . connect ( s e l f . q u i t )
10 s e l f . __actionUndo . t r i g g e r e d . c o n n e c t ( s e l f . undo )
11 s e l f . __actionRedo . t r i g g e r e d . c o n n e c t ( s e l f . r e d o )
12 s e l f . _ _ ac ti o nC ut . t r i g g e r e d . c o n n e c t ( s e l f . c u t )
13 s e l f . __actionCopy . t r i g g e r e d . c o n n e c t ( s e l f . copy )
14 s e l f . __actionPaste . t r i g g e r e d . connect ( s e l f . paste )
15 # ...
Ce nouveau menu accepte deux méthodes, addAction(action) qui ajoute une action au menu,
et la méthode addSeparator() qui ajoute un séparateur.
1 c l a s s B l o c N o t e s ( QtWidgets . QMainWindow ) :
2 d e f __init__ ( s e l f , p a r e n t=None ) :
3 QtWidgets . QMainWindow . __init__ ( s e l f , p a r e n t )
4 # ...
5 s e l f . __menuFile = s e l f . menuBar ( ) . addMenu ( " F i c h i e r " )
6 s e l f . __menuFile . a d d A c t i o n ( s e l f . __actionNew )
7 s e l f . __menuFile . a d d A c t i o n ( s e l f . __actionOpen )
8 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n S a v e )
9 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n S a v e A s )
10 s e l f . __menuFile . a d d S e p a r a t o r ( )
11 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n Q u i t )
12 s e l f . __menuEdit = s e l f . menuBar ( ) . addMenu ( "É d i t i o n " )
13 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionUndo )
14 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionRedo )
114 CHAPITRE 10. LES INTERFACES GRAPHIQUES
15 s e l f . __menuEdit . a d d S e p a r a t o r ( )
16 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __ ac t io nC u t )
17 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionCopy )
18 s e l f . __menuEdit . a d d A c t i o n ( s e l f . _ _ a c t i o n P a s t e )
19 # ...
41 s e l f . __actionOpen . t r i g g e r e d . c o n n e c t ( s e l f . openDocument )
42 s e l f . _ _ a c t i o n S a v e . t r i g g e r e d . c o n n e c t ( s e l f . saveDocument )
43 s e l f . _ _ a c t i o n S a v e A s . t r i g g e r e d . c o n n e c t ( s e l f . saveAsDocument )
44 s e l f . __actionQuit . t r i g g e r e d . connect ( s e l f . q u i t )
45 s e l f . __actionUndo . t r i g g e r e d . c o n n e c t ( s e l f . undo )
46 s e l f . __actionRedo . t r i g g e r e d . c o n n e c t ( s e l f . r e d o )
47 s e l f . _ _ ac ti o nC ut . t r i g g e r e d . c o n n e c t ( s e l f . c u t )
48 s e l f . __actionCopy . t r i g g e r e d . c o n n e c t ( s e l f . copy )
49 s e l f . __actionPaste . t r i g g e r e d . connect ( s e l f . paste )
50 s e l f . __menuFile = s e l f . menuBar ( ) . addMenu ( " F i c h i e r " )
51 s e l f . __menuFile . a d d A c t i o n ( s e l f . __actionNew )
52 s e l f . __menuFile . a d d A c t i o n ( s e l f . __actionOpen )
53 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n S a v e )
54 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n S a v e A s )
55 s e l f . __menuFile . a d d S e p a r a t o r ( )
56 s e l f . __menuFile . a d d A c t i o n ( s e l f . _ _ a c t i o n Q u i t )
57 s e l f . __menuEdit = s e l f . menuBar ( ) . addMenu ( "É d i t i o n " )
58 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionUndo )
59 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionRedo )
60 s e l f . __menuEdit . a d d S e p a r a t o r ( )
61 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __ ac t io nC u t )
62 s e l f . __menuEdit . a d d A c t i o n ( s e l f . __actionCopy )
63 s e l f . __menuEdit . a d d A c t i o n ( s e l f . _ _ a c t i o n P a s t e )
64 s e l f . _ _ b a r r e F i l e = s e l f . addToolBar ( " F i c h i e r " )
65 s e l f . _ _ b a r r e F i l e . a d d A c t i o n ( s e l f . __actionNew )
66 s e l f . _ _ b a r r e F i l e . a d d A c t i o n ( s e l f . __actionOpen )
67 s e l f . __barreFi le . addAction ( s e l f . __actionSave )
68 s e l f . _ _ b a r r e E d i t = s e l f . addToolBar ( "É d i t i o n " )
69 s e l f . _ _ b a r r e E d i t . a d d A c t i o n ( s e l f . __actionUndo )
70 s e l f . _ _ b a r r e E d i t . a d d A c t i o n ( s e l f . __actionRedo )
71 s e l f . _ _ b a r r e E d i t . a d d A c t i o n ( s e l f . __ ac t io nC u t )
72 s e l f . _ _ b a r r e E d i t . a d d A c t i o n ( s e l f . __actionCopy )
73 s e l f . __barreEdit . addAction ( s e l f . __actionPaste )
74 s e l f . show ( )
75 def fonct ( s e l f ) :
76 pass
77 app = QtWidgets . Q A p p l i c a t i o n ( s y s . a r g v )
78 f e n e t r e = B l o c N o t e s ( )
79 app . exec_ ( )
10.6 Exercices
Vous êtes nouvellement embauché dans une entreprise en bâtiment pour créer un programme
permettant au secrétariat de saisir les estimations de travaux de l’entreprise. Votre application devra
s’interfacer avec une base de données SQLite qui stockera le catalogue des prestations proposées par
l’entreprise et leurs tarifs. Cette base de données contiendra également les estimations déjà réalisées.
Pour créer une estimation, il faut d’abord saisir les informations relatives au client (nom, prénom,
adresse, code postal, ville, téléphone, courriel), le titre du chantier, puis choisir dans le catalogue les
prestations à ajouter. Chaque prestation est dans une catégorie et comporte un texte la décrivant,
un prix unitaire et une unité (définissant le prix unitaire). Voici un exemple :
Prestation Prix unitaire (e/unité) Unité
Cloison sur ossature métallique. 45 m2
Si la prestation n’existe pas, une boîte de dialogue permet d’en ajouter, de même pour les ca-
tégories. Lors de l’ajout d’une prestation à l’estimation, l’utilisateur doit choisir un taux de TVA
(exprimé en %). Une fois la saisie de la prestation terminée, les totaux hors-taxes, de TVA et le total
TTC (hors-taxes + TVA) sont automatiquement mis à jour.
118 CHAPITRE 10. LES INTERFACES GRAPHIQUES
Enfin, il sera possible d’exporter l’estimation au format texte suivant l’exemple ci-dessous :
Société Bati Plus
52 rue de Clairecombe
74930 Moulincourbe
Lionel Paulin
48 Ruelle de Locvaux
74019 Mivran
01 98 74 30 52
lionel.paulin@exemple.com
Estimation numéro 524 réalisée le 10 avril 2017.
Chantier de plâtrerie
Prestation Prix unitaire Quantité Total HT TVA Total TTC
Cloison sur ossature 45 e/m2 17 m2 765e 153e 918e
métallique (20%)
Pose d’une porte 78 e/porte 1 porte 78e 15,6e 93,6e
(20%)
Total HT : 843e
Total TVA : 168,6e
Total TTC : 1011,6e
Une base de données est un ensemble cohérent de données structurées permettant d’accéder à
celle-ci de manière rapide. À l’inverse d’un fichier texte, celle-ci est structurée et peut être utilisée
par différents programmes ou systèmes en même temps.
A.1 Terminologie
Une base de données est composée d’entités, nommées également tables, contenant des in-
formations les détaillants. Chaque table est composée d’attributs, nommés également champs ou
colonnes décrivant ces entités. Chaque entité possède des enregistrements, elles sont décrites
par les différents attributs. Chaque enregistrement doit être identifié par un attribut unique appelé
clé primaire. Cette clé primaire peut être une information déjà présente dans la table et revêtant
un caractère unique (No de sécurité sociale, référence produit . . .). Si aucune entité ne peut être
désignée comme clé primaire, l’utilisation d’un entier choisi arbitrairement pour jouer ce rôle est très
fréquent. L’exemple ci-dessous permet d’illustrer ces termes (fig. A.1).
Personnes
id nom prenom adresse codePostal ville ← Les attributs
1 Martin Jean 12 rue des mimosas 71400 Autun
2 Martin Pauline 41 av. Charlemagne 83000 Toulon ← Un enregistrement
3 Maigret Emmanuel 85 rue de la tour 71400 Autun
↑ Clé primaire
121
122 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
SQLite3 Il s’agit d’une bibliothèque écrite en C dans le domaine public permettant d’interagir avec
des bases de données stockées dans des fichiers. À l’inverse de MariaDB, il ne repose pas sur
une architecture client/serveur. Ce système est particulièrement adapté pour les petites bases
de données stockées localement, comme alternative aux fichiers texte.
Nous présenterons des types de données pour MariaDB/MySQL et pour SQLite3. Ces deux sys-
tèmes partagent une même valeur : NULL qui signifie valeur vide. De plus, ces deux systèmes ne
stockent pas les booléens. Pour y remédier, vous pouvez utiliser un type INT(1) pour MariaDB/-
MySQL ou INTEGER dans lequel la valeur faux serait stockée par le nombre 0 et vrai par le nombre
1.
Les données texte permettent de stocker des chaînes de caractères. Voici les différents types de
données (table A.1).
L’ensemble des types de valeurs présentées ici peuvent être signés (UNSIGNED) ou non. Une valeur
signée (par défaut) permet les valeurs négatives alors que les valeurs non signées non. Cependant,
une valeur normale permettra des valeurs comprises entre la moitié de la borne non signée en négatif
et en positif. Par exemple, pour les valeurs TINYINT, en fonctionnement normal, admet des valeurs
entre -128 et 127 alors que la valeur non signée permet des valeurs entre 0 et 255. Voici la liste des
données numériques (table A.2).
Les types de données détaillés ici permettent de stocker une date et/ou une heure. Voici la liste
des données temporelles (table A.3).
124 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
SQLite3 ne prend pas en charge le stockage des données temporelles. Pour stocker ce type de
données, vous pouvez :
— Utiliser une variable TEXT et stocker la date sous la forme AAAA-MM-JJ HH:MI:SS.
— Utiliser une variable INTEGER et stocker la date sous la forme d’un horodatage (timestamp)
UNIX, à savoir le nombre de secondes depuis le 1er janvier 1970 à minuit (UTC).
naissance d’une personne et non son âge car cette donnée devra être modifiée régulièrement
pour être à jour.
— Éviter les redondances d’informations au sein de vos tables car en cas de mise à jour de l’une
de ces informations, toutes les copies de celle-ci devront être mises à jour et ceci peut être
fastidieux et source d’erreurs.
Afin de résoudre le problème de cette dernière règle, nous faisons appel à des clés étrangères. Il
s’agit d’une copie de la clé primaire de l’enregistrement que l’on souhaite lier.
Par exemple, voici une base de données pour gérer les emprunts dans une bibliothèque (table A.5).
Emprunts
id nom prenom refLivre livre auteur dateEmprunt dateRetour
1 Martin Jean ACL7463 Germinal Émile Zola 16/03/2017
2 Duval Marie ACL7463 Germinal Émile Zola 12/02/2017 26/02/2017
3 Martin Jean JBV1337 Le Cid Corneille 30/11/2016 13/12/2016
4 Duval Marie ACL7463 Germinal Émile Zola 28/06/2016 14/07/2016
On observe que des données sont répétées plusieurs fois dans cette table. Pour y remédier, nous
allons la scinder en trois tables : Client stockant les données du client, Livres décrivant les
informations sur le livre et Emprunts associant un client à un livre et donnant des informations sur
l’emprunt (table A.6).
Clients Livres
id nom prenom refLivre livre auteur
1 Martin Jean ACL7463 Germinal Émile Zola
2 Duval Marie JBV1337 Le Cid Corneille
Emprunts
id idClient refLivre dateEmprunt dateRetour
1 1 ACL7463 16/03/2017
2 2 ACL7463 12/02/2017 26/02/2017
3 1 JBV1337 30/11/2016 13/12/2016
4 2 ACL7463 28/06/2016 14/07/2016
Dans cet exemple, les champs idClient et refLivre sont des clés étrangères car elles font
référence respectivement aux clés primaires des tables Clients et Livres.
Nous verrons plus tard comment reformer la table initiale via l’opération de jointure.
126 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
Personnes
id : INT
nom : TINYTEXT
prenom : TINYTEXT
adresse : TEXT
codePostal : CHAR(5)
ville : TEXT
La liaison entre deux tables, en utilisant le système de clés primaires et étrangères, se fait avec
une flèche reliant les deux tables. Pour illustrer cela, nous allons reprendre comme exemple la base
de données bibliothèque expliquée plus haut (fig. A.3).
Emprunts
Clients Livres
id : INT
id : INT idClient : INT refLivre : CHAR(7)
nom : TINYTEXT refLivre : CHAR(7) livre : TINYTEXT
prenom : TINYTEXT dateEmprunt : DATE auteur : TINYTEXT
dateRetour : DATE
Pour plus de clarté, il est recommandé de positionner les liens en vis-à-vis des lignes décrivant les
clés primaires et étrangères.
Cette ligne indique que l’interpréteur est prêt à exécuter des commandes SQL. Le contenu des
crochets (ici (none)) indique sur quelle base de données l’interpréteur va travailler (ici, aucune).
Une fois connectés au SGBD, nous allons tout d’abord voir comment naviguer dans les différentes
bases et tables présentes dans celui-ci.
Vous pouvez afficher la liste des bases de données présentes avec SHOW DATABASES :
Une fois votre base de données sélectionnée, vous pouvez afficher les tables d’une base de données
avec SHOW TABLES :
Key Affiche si le champ est une clé primaire (PRI) ou étrangère (MUL).
Extra Affiche des informations supplémentaires sur le champ telles que l’auto-incrémentation 1 .
Pour créer une base de données, utilisez la commande CREATE TABLE. Voici un exemple avec la
table Emprunts :
1 CREATE TABLE B i b l i o t h e q u e . Emprunts (
2 i d INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
3 i d C l i e n t INT UNSIGNED NOT NULL ,
4 r e f L i v r e CHAR( 7 ) NOT NULL ,
5 dateEmprunt DATE NOT NULL ,
6 d a t e R e t o u r DATE DEFAULT ’ 0000−00−00 0 0 : 0 0 : 0 0 ’ ,
7 FOREIGN KEY ( i d C l i e n t ) REFERENCES B i b l i o t h e q u e . C l i e n t s ( i d ) ,
8 FOREIGN KEY ( r e f L i v r e ) REFERENCES B i b l i o t h e q u e . L i v r e s ( r e f L i v r e )
9 )
10 ENGINE=InnoDB DEFAULT CHARSET=u t f 8 ;
— Pour MariaDB : Une fois les attributs et les contraintes déclarés, on referme la parenthèse,
puis on définit le moteur de base de données (ici InnoDB, par défaut) puis l’encodage (ici
UTF8, recommandé). On termine la ligne par un point-virgule.
Créer un index
La création d’un index se fait avec la commande CREATE INDEX. Un index permet d’accélérer
les opérations sur les grandes tables. Voici comment créer un index :
1 CREATE INDEX i n d e x E m p r u n t s ON Emprunts ;
Il est également possible de le faire sur un ou plusieurs attributs :
1 CREATE INDEX i n d e x E m p r u n t s ON Emprunts ( r e f L i v r e , i d C l i e n t ) ;
Ajouter un attribut
Modifier un attribut
Il est possible par cette commande de changer le type de données pour un attribut :
1 ALTER TABLE B i b l i o t h e q u e . L i v r e s MODIFY l i v r e TEXT ;
Renommer un attribut
Dans l’exemple ci-dessus, on renomme l’attribut livre en titreLivre dans la table Livres.
Supprimer un attribut
1 DROP DATABASE B i b l i o t h e q u e ;
Nous allons voir la première méthode, à savoir en renseignant tous les attributs :
Dans l’exemple ci-dessus, on ne renseigne pas le champ id car ce champ s’incrémente automati-
quement. On ne renseigne pas non plus le champ dateRetour car le client n’a pas encore retourné
le livre.
Cette instruction modifie la valeur de l’attribut dateRetour en lui attribuant la valeur 2017-03-05,
ainsi que l’attribut refLivre en lui attribuant la valeur MAP112 à tous les enregistrements de
la table.
L’astérisque (*) permet d’afficher toutes les colonnes de la table. Il est cependant possible de
spécifier les attributs que l’on souhaite voir apparaître dans le résultat :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT r e f L i v r e , l i v r e FROM B i b l i o t h e q u e .
Livres ;
2 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
3 | refLivre | livre |
4 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
5 | ACL7463 | G e r m i n a l |
6 | ALC103 | 20000 l i e u e s s o u s l e s mers |
7 | EIF012 | L e s Mis é r a b l e s |
8 | GTR089 | Le P e t i t P r i n c e |
9 | JBV1337 | Le C i d |
10 | MAP112 | Rhinoc é r o s |
11 | NNA2104 | Thé r è s e Raquin |
12 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
13 7 rows i n s e t ( 0 . 0 0 s e c )
Pour simplifier la lecture du résultat ou pour raccourcir l’écriture d’une requête, il est possible
d’affecter temporairement un alias à une table ou à un attribut avec la commande AS dont en voici
un exemple :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT r e f L i v r e , l i v r e AS ‘ c1 ‘ FROM
B i b l i o t h e q u e . L i v r e s AS t 1 ;
2 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
3 | r e f L i v r e | c1 |
4 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
5 | ACL7463 | G e r m i n a l |
6 | ALC103 | 20000 l i e u e s s o u s l e s mers |
7 | EIF012 | L e s Mis é r a b l e s |
8 | GTR089 | Le P e t i t P r i n c e |
9 | JBV1337 | Le C i d |
10 | MAP112 | Rhinoc é r o s |
134 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
Dans l’exemple précédent, on observe que le nom de l’alias est entre backquote (symbole ‘, obtenu
avec la combinaison des touches Alt Gr + 7 ), ce qui permet de délimiter le nom du champ. Ceci
est obligatoire lorsque celui-ci comporte un espace. La colonne livre est renommée en c1 et la
table Livres en t1. Cette dernière opération s’avérera utile lors des jointures.
Les jointures permettent d’utiliser plusieurs tables dans la même requête. C’est avec cette opé-
ration que l’on tire parti des relations de clés primaires et étrangères car on reconstruit la table
originale (fig. A.5 et A.6).
Il existe plusieurs types de jointures, mais nous n’aborderons que la forme la plus courante,
l’intersection de deux tables ou INNER JOIN. Cette opération permet de retenir les enregistrements
des deux tables remplissant la condition. On obtient l’intersection des deux ensembles (fig. A.4).
INNER JOIN
Table A Table B
Nous allons illustrer cela en affichant les emprunts dans la bibliothèque et en mettant en vis-à-vis
le titre des œuvres :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT Emprunts . i d , Emprunts . dateEmprunt ,
Emprunts . i d C l i e n t , L i v r e s . l i v r e , L i v r e s . a u t e u r FROM Emprunts
INNER JOIN L i v r e s on Emprunts . r e f L i v r e = L i v r e s . r e f L i v r e ;
2 +−−−−+−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
3 | i d | dateEmprunt | i d C l i e n t | l i v r e | auteur |
4 +−−−−+−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
5 | 1 | 2017−03−16 | 1 | Germinal | Émile Zola |
6 | 2 | 2017−02−12 | 2 | Germinal | Émile Zola |
7 | 3 | 2016−11−30 | 1 | Le C i d | Corneille |
8 | 4 | 2016−06−28 | 2 | Germinal | Émile Zola |
9 | 5 | 2017−03−01 | 2 | R h i n o c é r o s | Eug è ne I o n e s c o |
10 +−−−−+−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
11 5 rows i n s e t ( 0 . 0 0 s e c )
A.8. LES INSTRUCTIONS DU LANGAGE DE MANIPULATION DE DONNÉES (LMD) 135
On peut chaîner cette opération : nous allons ici remplacer le numéro de client par le nom et le
prénom des emprunteurs :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT e . i d , e . dateEmprunt , c . nom , c . prenom , l . l i v r e , l .
a u t e u r FROM Emprunts AS e INNER JOIN L i v r e s AS l on e . r e f L i v r e = l . r e f L i v r e
INNER JOIN C l i e n t s AS c ON e . i d C l i e n t = c . i d ;
2 +−−−−+−−−−−−−−−−−−−+−−−−−−−−+−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
3 | i d | dateEmprunt | nom | prenom | l i v r e | auteur |
4 +−−−−+−−−−−−−−−−−−−+−−−−−−−−+−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
5 | 1 | 2017−03−16 | M a r t i n | Jean | Germinal | Émile Zola |
6 | 2 | 2017−02−12 | Duval | M a r i e | G e r m i n a l | Émile Zola |
7 | 3 | 2016−11−30 | M a r t i n | Jean | Le C i d | Corneille |
8 | 4 | 2016−06−28 | Duval | M a r i e | G e r m i n a l | Émile Zola |
9 | 5 | 2017−03−01 | Duval | M a r i e | R h i n o c é r o s | Eug è ne I o n e s c o |
10 +−−−−+−−−−−−−−−−−−−+−−−−−−−−+−−−−−−−−+−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−+
11 5 rows i n s e t ( 0 . 0 0 s e c )
Pour lever toute ambiguïté lors de la désignation des attributs, on nomme ceux-ci de la forme
suivante : table.attribut. Vous remarquerez dans l’exemple ci-dessus une utilisation astucieuse
des alias qui permet de réduire la longueur de la requête.
L’instruction WHERE, qui peut être utilisée avec des instructions telles que SELECT, DELETE ou
encore UPDATE, fournit un vaste champ de possibilités pour effectuer des comparaisons. Voici une
liste des opérateurs de comparaison couramment utilisés (table A.7).
Comparateur Syntaxe
a égal à b a = b
a différent de b a <> b ou a != b
a supérieur à b a > b
a supérieur ou égal à b a >= b
a inférieur à b a < b
a inférieur ou égal à b a <= b
a dans b a IN b
a entre b et c a BETWEEN b AND c
a dans b (selon le modèle) a LIKE b
a est nul a IS NULL
a n’est pas nul a IS NOT NULL
Le comparateur IN permet de vérifier si une valeur est dans un ensemble de données. Cela peut
être une liste de données. On affiche ici les informations à propos des livres Germinal et Le Cid :
136 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
Cette liste de données peut être le résultat d’une sous-requête. On recherche ici les livres empruntés
après le 1er janvier 2017. :
L’opérateur BETWEEN permet de vérifier si la donnée est comprise entre deux bornes. Cette opé-
ration est possible pour les dates et les nombres. L’exemple suivant montre les emprunts souscrits
en 2016 :
Modèle Description
%gne Une chaîne se terminant par gne.
Mon% Une chaîne commençant par Mon.
%ta% Une chaîne contenant ta.
Bo_ Une chaîne de trois lettres commençant par Bo (exemple : Boa ou Bob).
Voici une application du comparateur LIKE dans laquelle on recherche les livres dont le titre se
termine par mers :
Il est possible de combiner des conditions avec AND (et) et OR (ou). Dans l’exemple suivant, on
affiche les livres écrits par Émile Zola et empruntés après le 1er janvier 2017.
A.8. LES INSTRUCTIONS DU LANGAGE DE MANIPULATION DE DONNÉES (LMD) 137
Organiser les résultats avec GROUP BY, ORDER BY, LIMIT et DESC
La commande ORDER BY permet de trier les résultats selon un attribut. Nous allons travailler
avec la table Livres. La commande suivante affiche les livres triés par auteur :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT ∗ FROM L i v r e s ORDER BY a u t e u r ;
2 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−+
3 | refLivre | livre | auteur |
4 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−+
5 | GTR089 | Le P e t i t P r i n c e | A n t o i n e de S a i n t Exup é r y |
6 | JBV1337 | Le C i d | Corneille |
7 | ACL7463 | G e r m i n a l | Émile Zola |
8 | NNA2104 | Thé r è s e Raquin | Émile Zola |
9 | MAP112 | Rhinoc é r o s | Eug è ne I o n e s c o |
10 | ALC103 | 20000 l i e u e s s o u s l e s mers | J u l e s Verne |
11 | EIF012 | L e s Mis é r a b l e s | V i c t o r Hugo |
12 +−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−+
13 7 rows i n s e t ( 0 . 0 0 s e c )
Il est possible de limiter le nombre de lignes lors de l’affichage des résultats avec la commande
LIMIT. Notre exemple affiche les trois derniers emprunts souscrits :
138 ANNEXE A. INTRODUCTION À LA BASE DE DONNÉES SQL
Enfin, pour travailler avec la commande GROUP BY, nous allons utiliser une autre table : la table
Produits. Voici cette nouvelle table :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT ∗ FROM P r o d u i t s ;
2 +−−−−+−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+−−−−−−+
3 | id | produit | categorie | prix |
4 +−−−−+−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+−−−−−−+
5 | 1 | Fromage f r a i s | Cr è m e r i e | 1.53 |
6 | 2 | Cr ème semi−é p a i s s e | Cr è m e r i e | 3.3 |
7 | 3 | Emmental r â p é | Cr è m e r i e | 1.44 |
8 | 4 | Comté 10 mois | Cr è m e r i e | 4.29 |
9 | 5 | Beurre | Cr è m e r i e | 1.31 |
10 | 6 | Raviolis frais | Traiteur | 1.59 |
11 | 7 | Gnocchi | Traiteur | 1.09 |
12 | 8 | Shampooing | Hygi è ne | 1.83 |
13 | 9 | Courgette | F r u i t s e t l é gumes | 2 . 5 9 |
14 | 10 | P o i v r o n r o u g e | F r u i t s e t l é gumes | 1 . 1 9 |
15 | 11 | Banane | F r u i t s e t l é gumes | 1 . 5 9 |
16 +−−−−+−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+−−−−−−+
17 11 rows i n s e t ( 0 . 0 0 s e c )
La commande suivante, utilisant l’instruction GROUP BY permet d’afficher le sous-total par caté-
gorie :
1 MariaDB [ B i b l i o t h e q u e ]> SELECT c a t e g o r i e , SUM( p r i x ) FROM P r o d u i t s
GROUP BY c a t e g o r i e ;
2 +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+
3 | categorie | SUM( p r i x ) |
4 +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+
5 | Cr è m e r i e | 11.869999885559082 |
6 | F r u i t s e t l é gumes | 5 . 3 7 0 0 0 0 0 0 4 7 6 8 3 7 2 |
7 | Hygi è ne | 1.8300000429153442 |
8 | Traiteur | 2.680000066757202 |
A.9. LES INSTRUCTIONS DU LANGAGE DE CONTRÔLE DE DONNÉES (LCD) 139
9 +−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−+
10 4 rows i n s e t ( 0 . 0 1 s e c )
1 DROP USER ’ a l a i n ’@ ’ l o c a l h o s t ’ ;
Commande Description
ALL Donne toutes les autorisations ci-dessous.
ALTER Autorise la commande ALTER TABLE.
CREATE Autorise la commande CREATE TABLE.
DELETE Autorise la commande DELETE.
DROP Autorise la commande DROP TABLE.
INDEX Autorise la gestion des index.
INSERT Autorise la commande INSERT.
SELECT Autorise la commande SELECT.
SHOW DATABASES Autorise la commande SHOW DATABASES.
UPDATE Autorise la commande UPDATE.
Fonction Description
SUM(valeurs) Renvoie la somme des valeurs.
MAX(valeurs) Renvoie le maximum des valeurs.
MIN(valeurs) Renvoie le minimum des valeurs.
AVG(valeurs) Renvoie la moyenne de valeurs.
COUNT(valeurs) Renvoie le nombre de valeurs.
ROUND(valeur) Renvoie un arrondi de la valeur.
UPPER(texte) Renvoie le texte en caractères majuscules.
LOWER(texte) Renvoie le texte en caractères minuscules.
NOW() Renvoie la date et l’heure actuelles.
RAND() Renvoie une valeur aléatoire.
SUBSTR(colonne, a, b) Renvoie la colonne tronquée à partir du aème caractère sur
b caractères.
1 # Sans l e s a f f e c t a t i o n s m u l t i p l e s :
2 q u a n t i t e C r a y o n s = 17
3 volumeEau = 1 4 . 2
4 m e t e o P a r i s = " Temps nuageux "
5 # Avec l e s a f f e c t a t i o n s m u l t i p l e s :
6 q u a n t i t e C r a y o n s , volumeEau , m e t e o P a r i s = 1 7 , 1 4 . 2 , " Temps
nuageux "
3. Écrivez les instructions permettant de calculer l’aire d’un disque. La formule est A = π × R2
avec A l’aire et R le rayon du disque valant ici 5 cm. Le résultat doit être affiché sous la forme
"L’aire du disque est de XXX cm2".
1 p i = 3.14159
2 R = 5
3 A = p i ∗ R∗∗2
4 p r i n t ( " L ’ a i r e du d i s q u e e s t de " ,A , "cm2" )
141
142 ANNEXE B. CORRIGÉS DES EXERCICES
2. Écrivez un programme permettant, à partir d’un montant hors taxes saisi par l’utilisateur, de
calculer le montant de la TVA (20% du montant hors taxes) et du montant TTC (montant
hors taxes auquel on ajoute le montant de la TVA) et donnez le détail du calcul.
1 #! / u s r / b i n / env p y t h o n 3
2 montantHT = f l o a t ( i n p u t ( " E n t r e z l e montant HT : " ) )
3 montantTVA = montantHT ∗ 0 . 2 # Taux de TVA : 20%
4 montantTTC = montantHT + montantTVA
5 p r i n t ( " Montant HT : " , montantHT )
6 p r i n t ( "TVA 20% : " , montantTVA )
7 p r i n t ( " Montant TTC : " , montantTTC )
3. Écrivez un programme vérifiant si dans un texte saisi par l’utilisateur, celui-ci contient le mot
"fraise" ou le mot "pêche".
B.3. FACTORISER LE CODE 143
1 #! / u s r / b i n / env p y t h o n 3
2 t e x t e = i n p u t ( " E n t r e z un t e x t e : ")
3 i f " f r a i s e " in texte :
4 p r i n t ( " Le t e x t e c o n t i e n t l e mot f r a i s e . " )
5 e l i f " p ê che " i n t e x t e :
6 p r i n t ( " Le t e x t e c o n t i e n t l e mot p ê che . " )
7 else :
8 p r i n t ( " Le t e x t e ne c o n t i e n t n i l e mot p ê che ou f r a i s e . " )
1 #! / u s r / b i n / env p y t h o n 3
2 def addition (a , b) :
3 r e t u r n ( a+b )
4 def soustraction (a , b) :
5 r e t u r n ( a−b )
6 def m u l t i p l i c a t i o n (a , b) :
7 r e t u r n ( a ∗b )
8 def d i v i s i o n (a , b) :
9 r e t u r n ( a /b )
10 def c a l c u l a t r i c e () :
11 nombreA = f l o a t ( i n p u t ( " E n t r e z l e p r e m i e r nombre : " ) )
12 nombreB = f l o a t ( i n p u t ( " E n t r e z l e s e c o n d nombre : " ) )
13 o p e r a t i o n = i n t ( i n p u t ( " E n t r e z l ’ op é r a t i o n (1=+, 2=−, 3=X ,
4=:) : " ) )
14 resultat = 0
15 i f o p e r a t i o n == 1 :
16 r e s u l t a t = a d d i t i o n ( nombreA , nombreB )
17 e l i f o p e r a t i o n == 2 :
18 r e s u l t a t = s o u s t r a c t i o n ( nombreA , nombreB )
19 e l i f o p e r a t i o n == 3 :
20 r e s u l t a t = m u l t i p l i c a t i o n ( nombreA , nombreB )
21 e l i f o p e r a t i o n == 4 :
22 r e s u l t a t = d i v i s i o n ( nombreA , nombreB )
23 else :
24 p r i n t ( "Opé r a t i o n non p r i s e en c h a r g e . " )
25 p r i n t ( " Le r é s u l t a t e s t " , s t r ( r e s u l t a t ) )
26 c a l c u l a t r i c e ()
1 #! / u s r / b i n / env p y t h o n 3
2 comptes = { " P a u l " : 1 5 4 . 7 4 , " M a r i e " : 4 1 8 . 4 5 , " Jean " : 9 6 . 2 0 , " P a u l i n e "
:914.21}
3 def depot ( c l i e n t ) :
4 montant = f l o a t ( i n p u t ( " Quel montant v o u l e z −v o u s d é p o s e r ? " ) )
5 comptes [ c l i e n t ] += montant
6 p r i n t ( "Opé r a t i o n e f f e c t u é e . " )
7 def r e t r a i t ( c l i e n t ) :
8 montant = f l o a t ( i n p u t ( " Quel montant v o u l e z −v o u s r e t i r e r ? " ) )
9 i f montant <= comptes [ c l i e n t ] :
10 comptes [ c l i e n t ] −= montant
11 p r i n t ( "Opé r a t i o n e f f e c t u é e . " )
12 else :
13 p r i n t ( "Opé r a t i o n i m p o s s i b l e : v o t r e s o l d e e s t i n s u f f i s a n t .
")
14 w h i l e True :
15 p r i n t ( " Banque \n " )
16 print ( " Client \ tSolde " )
17 p r i n t ( "−−−−−−−−−−−−−−−" )
18 f o r c l i e n t , s o l d e i n comptes . i t e m s ( ) :
19 p r i n t ( c l i e n t + "\t " + s t r ( solde ) )
20 print ("")
21 o p e r a t i o n = i n p u t ( " C h o i s i s s e z une op é r a t i o n (D : Dé p o t − R :
R e t r a i t − Q : Q u i t t e r ) : " ) . upper ()
22 i f o p e r a t i o n == "D" :
23 c l i e n t = i n p u t ( " E n t r e z l e nom du c l i e n t s u r l e q u e l
e f f e c t u e r l e dé pot : " )
24 depot ( c l i e n t )
25 e l i f o p e r a t i o n == "R" :
26 c l i e n t = i n p u t ( " E n t r e z l e nom du c l i e n t s u r l e q u e l
effectuer le retrait : ")
27 retrait ( client )
28 e l i f o p e r a t i o n == "Q" :
29 p r i n t ( "Au r e v o i r " )
30 break
31 else :
32 p r i n t ( "Opé r a t i o n i n c o r r e c t e . " )
1 #! / u s r / b i n / env p y t h o n 3
2 from random i m p o r t r a n d i n t
146 ANNEXE B. CORRIGÉS DES EXERCICES
3 nombresUtilisateur = []
4 t i r a g e = [ randint (1 ,50) f o r i in range (6) ]
5 while len ( nombresUtilisateur ) < 6:
6 numero = i n t ( i n p u t ( " E n t r e z l e " + s t r ( l e n ( n o m b r e s U t i l i s a t e u r )
+1) + " e numé r o e n t r e 1 e t 50 i n c l u s : " ) )
7 i f numero >= 1 and numero <= 5 0 :
8 n o m b r e s U t i l i s a t e u r . append ( numero )
9 p r i n t ( " Votre choix : " + " − " . j o i n ( s t r ( i ) f o r i i n
nombresUtilisateur ) )
10 p r i n t ( " Le t i r a g e : " + " − " . j o i n ( s t r ( i ) f o r i i n t i r a g e ) )
11 s c o r e = 0
12 f o r nombre i n t i r a g e :
13 i f nombre i n n o m b r e s U t i l i s a t e u r :
14 s c o r e += 1
15 p r i n t ( " Vous a v e z " + s t r ( s c o r e ) + " nombres g a g n a n t s . " )
3. Écrivez un programme permettant de vérifier si un mot ou une phrase saisis par l’utilisateur
est un palindrome, à savoir un mot lisible à la fois à l’endroit ou à l’envers tel que Serres,
radar, rotor ou "Ésope reste ici et se repose" :
1 #! / u s r / b i n / env p y t h o n 3
2 p h r a s e = i n p u t ( " E n t r e z un mot ou une p h r a s e : " ) . r e p l a c e ( " " , " " )
. upper ()
3 i n v e r s e = phrase [:: −1]
4 i f p h r a s e == i n v e r s e :
5 p r i n t ( " La p h r a s e e s t un p a l i n d r o m e . " )
6 else :
7 p r i n t ( " La p h r a s e n ’ e s t p a s un p a l i n d r o m e . " )
1 #! / u s r / b i n / env p y t h o n 3
2 nomsJours = ( " Samedi " , " Dimanche " , " L u n d i " , " Mardi " , " M e r c r e d i " , "
Jeudi " , " Vendredi " )
3 nomsMois = ( " j a n v i e r " , " f é v r i e r " , " mars " , " a v r i l " , " mai " , " j u i n " , "
j u i l l e t " , " ao û t " , " s e p t e m b r e " , " o c t o b r e " , " novembre " , " d é cembre " )
4 nombresJoursParMois = (31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31)
5 indexJour = 0
6 f o r nombreJours , mois i n z i p ( n o m b r e s J o u r s P a r M o i s , nomsMois ) :
7 f o r j o u r i n r a n g e ( 1 , n o m b r e J o u r s +1) :
8 p r i n t ( nomsJours [ i n d e x J o u r ] + " " + s t r ( j o u r ) + " " + mois )
9 i n d e x J o u r = ( i n d e x J o u r +1)%7
B.4. LES SÉQUENCES 147
Mélanger farine et levure, ajouter le beurre, le sucre et pétrir avec les doigts. Ajouter l’œuf
battu et le lait. Bien mélanger. Fariner la boule de pâte, étaler la pâte sur 1/2 cm et découper
des formes avec un emporte-pièce. Cuire 12 à 15 minutes à 190◦ C.
1 #! / u s r / b i n / env p y t h o n 3
2 recette = {
3 " Farine " :{ " quantite " :15 , " unite " : "g" } ,
4 " Beurre " :{ " quantite " : 3 . 7 5 , " unite " : "g" } ,
5 " Sucre roux " :{ " q u a n t i t e " : 3 . 7 5 , " u n i t e " : "g" } ,
6 " Oeuf " : { " q u a n t i t e " : 0 . 0 5 , " u n i t e " : " " } ,
7 " L a i t " : { " q u a n t i t e " : 2 . 5 , " u n i t e " : " ml " } ,
8 " Levure chimique " :{ " quantite " :0.025 , " unite " : " sachet " } ,
9 " Sucre v a n i l l é " :{ " q u a n t i t e " : 0 . 0 5 , " u n i t e " : " sachet "}
10 } # Par b i s c u i t
11 q u a n t i t e = i n t ( i n p u t ( " E n t r e z l e nombre de b i s c u i t s à p r o d u i r e (
p a r m u l t i p l e de 2 0) : " ) )
12 f o r i n g r e d i e n t , d o n n e e s i n r e c e t t e . i t e m s ( ) :
13 p r i n t ( " − " + i n g r e d i e n t + " : " + s t r ( donnees [ " q u a n t i t e " ]∗
q u a n t i t e ) + donnees [ " u n i t e " ] )
14 # Permet un a f f i c h a g e de c e t y p e : " − F a r i n e : 300 g "
6. Écrivez un programme affichant le mot le plus long d’une phrase entrée par l’utilisateur.
1 #! / u s r / b i n / env p y t h o n 3
2 p h r a s e = i n p u t ( " E n t r e z une p h r a s e : " )
3 mots = p h r a s e . s p l i t ( " " )
4 motPlusLong = " "
5 tailleMotPlusLong = 0
6 f o r mot i n mots :
7 t a i l l e M o t = l e n ( mot )
8 i f t a i l l e M o t >= t a i l l e M o t P l u s L o n g :
9 motPlusLong = mot
10 tailleMotPlusLong = tailleMot
11 p r i n t ( " Le mot l e p l u s l o n g e s t " + motPlusLong . u p p e r ( ) + " a v e c
" + str ( tailleMotPlusLong ) + " l e t t r e s . ")
7. Écrivez un programme permettant de trier une liste de nombres sans utiliser la méthode
sort(). Réécrivez une fonction de tri de liste avec l’algorithme de tri à bulles qui consiste à
148 ANNEXE B. CORRIGÉS DES EXERCICES
comparer deux valeurs consécutives d’une liste et de les permuter quand elles sont mal triées et
de répéter cela jusqu’à ce que la liste soit triée. Vous utiliserez les nombres tirés aléatoirement.
1 #! / u s r / b i n / env p y t h o n 3
2 from random i m p o r t r a n d i n t
3 l i s t e A T r i e r = [ randint (1 ,50) f o r i in range (15) ]
4 p r i n t ( " La l i s t e a v a n t l e t r i : " + " − " . j o i n ( s t r ( i ) f o r i i n
listeATrier ))
5 changement = True
6 w h i l e changement :
7 changement = F a l s e
8 f o r idx in range (1 , len ( l i s t e A T r i e r ) ) :
9 i f l i s t e A T r i e r [ i d x ] < l i s t e A T r i e r [ idx −1]:
10 l i s t e A T r i e r [ i d x ] , l i s t e A T r i e r [ i d x −1] = l i s t e A T r i e r [ i d x
−1] , l i s t e A T r i e r [ i d x ]
11 changement = True
12 p r i n t ( " La l i s t e a p r è s l e t r i : " + " − " . j o i n ( s t r ( i ) f o r i i n
listeATrier ))
10 l e t t r e s E s s a y e e s = [ ]
11 c h a n c e s = 7
12 motTrouve = F a l s e
13 w h i l e motTrouve == F a l s e and c h a n c e s > 0 :
14 masque= " "
15 motTrouve = True
16 f o r l e t t r e i n motADeviner :
17 i f l e t t r e in lettresEssayees :
18 masque += l e t t r e + " "
19 else :
20 masque += "− "
21 motTrouve = F a l s e
22 i f motTrouve == F a l s e :
23 p r i n t ( masque + " ( " + s t r ( c h a n c e s ) + " c h a n c e s ) . " )
24 l e t t r e P r o p o s e e = i n p u t ( " E n t r e z une l e t t r e : " ) . u p p e r ( )
25 l e t t r e s E s s a y e e s . append ( l e t t r e P r o p o s e e )
26 i f l e t t r e P r o p o s e e n o t i n motADeviner :
27 c h a n c e s −= 1
28 i f motTrouve :
29 p r i n t ( " Bravo ! Le mot é t a i t " + motADeviner )
30 e l s e :
31 p r i n t ( " Perdu ! Le mot é t a i t " + motADeviner )
1 #! / u s r / b i n / env p y t h o n 3
2 d i s t a n c e = i n t ( i n p u t ( " E n t r e z l a d i s t a n c e de c h i f f r e m e n t : " ) )
3 l e t t r e s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4 f i c h i e r C l a i r = open ( " t e x t e . t x t " , " r t " )
5 f i c h i e r C h i f f r e = open ( " c h i f f r e . t x t " , " wt " )
6 for l i g n e C l a i r in f i c h i e r C l a i r . readlines () :
7 l i g n e C l a i r = l i g n e C l a i r . r e p l a c e ( " \n " , " " )
8 ligneChiffre = ""
9 for caractereClair in ligneClair :
10 c a r a c t e r e C l a i r = c a r a c t e r e C l a i r . upper ()
11 caractereChiffre = ""
12 i f caractereClair in l e t t r e s :
13 indexCaractereClair = l e t t r e s . index ( caractereClair )
14 c a r a c t e r e C h i f f r e = l e t t r e s [ ( i n d e x C a r a c t e r e C l a i r+
150 ANNEXE B. CORRIGÉS DES EXERCICES
d i s t a n c e ) %26]
15 else :
16 c a r a c t e r e C h i f f r e = c a r a c t e r e C l a i r # Pour l e s c a r a c t è r e s
non a l p h a b e t i q u e s ( t r a i t s d ’ u n i o n , e s p a c e s . . . )
17 l i g n e C h i f f r e += c a r a c t e r e C h i f f r e
18 f i c h i e r C h i f f r e . w r i t e ( l i g n e C h i f f r e + " \n " )
19 f i c h i e r C l a i r . close ()
20 f i c h i e r C h i f f r e . close ()
3. Écrivez un programme permettant à partir d’un fichier texte en français d’en déduire la fré-
quence d’apparition des lettres qu’il contient. Le résultat de cette analyse sera consigné dans
un fichier JSON. Pour des statistiques fiables, prenez un texte assez long. Vous pouvez utiliser
une copie de Zadig, écrit par Voltaire, disponible ici : http://pastebin.com/raw/H6AxM54J
1 #! / u s r / b i n / env p y t h o n 3
2 import json
3 l e t t r e s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4 f r e q u e n c e = {}
5 f i c h i e r = open ( ’ Z a d i g . t x t ’ , ’ r t ’ )
6 for ligne in f i c h i e r . readlines () :
7 for caractere in ligne :
8 i f c a r a c t e r e not i n f r e q u e n c e . keys ( ) :
9 frequence [ caractere ] = 1
10 else :
11 f r e q u e n c e [ c a r a c t e r e ] += 1
12 f i c h i e r . close ()
13 s t a t i s t i q u e s = {}
14 for l e t t r e in l e t t r e s :
15 i f l e t t r e in frequence . keys () :
16 s t a t i s t i q u e s [ l e t t r e ] = frequence [ l e t t r e ]
17 else :
18 statistiques [ lettre ] = 0
19 f i c h i e r R e s u l t a t s = open ( ’ s t a t i s t i q u e s . j s o n ’ , ’ wt ’ )
20 f i c h i e r R e s u l t a t s . w r i t e ( j s o n . dumps ( s t a t i s t i q u e s , s o r t _ k e y s=True ) )
21 f i c h i e r R e s u l t a t s . close ()
À l’aide des statistiques d’apparition des lettres issues de l’exercice précédent, déduisez le
message en clair du texte ci-dessus.
1 #! / u s r / b i n / env p y t h o n 3
2 import json
3 l e t t r e s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4 f i c h i e r S t a t i s t i q u e s = open ( " s t a t i s t i q u e s . j s o n " , " r t " )
5 s t a t i s t i q u e R e f e r e n c e = json . loads ( f i c h i e r S t a t i s t i q u e s . read () )
6 f i c h i e r S t a t i s t i q u e s . close ()
7 f i c h i e r C h i f f r e = open ( " c h i f f r e . t x t " , " r t " )
8 l i g n e s C h i f f r e = f i c h i e r C h i f f r e . readlines ()
9 f i c h i e r C h i f f r e . close ()
10 s t a t i s t i q u e C h i f f r e = {}
11 for ligneChiffre in lignesChiffre :
12 for caractereChiffre in ligneChiffre :
13 i f caractereChiffre in l e t t r e s :
14 i f c a r a c t e r e C h i f f r e not i n s t a t i s t i q u e C h i f f r e . keys ( ) :
15 statistiqueChiffre [ caractereChiffre ] = 1
16 else :
17 s t a t i s t i q u e C h i f f r e [ c a r a c t e r e C h i f f r e ] += 1
18 lettrePlusFrequenteReference = ""
19 maximumFrequenceReference = 0
20 lettrePlusFrequenteChiffre = ""
21 maximumFrequenceChiffre = 0
22 for l e t t r e in l e t t r e s :
23 i f s t a t i s t i q u e R e f e r e n c e [ l e t t r e ] > maximumFrequenceReference :
24 maximumFrequenceReference = s t a t i s t i q u e R e f e r e n c e [ l e t t r e ]
25 lettrePlusFrequenteReference = lettre
26 i f l e t t r e in s t a t i s t i q u e C h i f f r e . keys () :
27 i f s t a t i s t i q u e C h i f f r e [ l e t t r e ] > maximumFrequenceChiffre :
28 maximumFrequenceChiffre = s t a t i s t i q u e C h i f f r e [ l e t t r e ]
29 lettrePlusFrequenteChiffre = lettre
30 distance = l e t t r e s . index ( lettrePlusFrequenteChiffre ) − l e t t r e s .
index ( lettrePlusFrequenteReference )
31 lignesClair = []
32 for ligneChiffre in lignesChiffre :
33 ligneClair = ""
34 for caractereChiffre in ligneChiffre :
35 i f caractereChiffre in l e t t r e s :
36 indexCaractereChiffre = l e t t r e s . index ( caractereChiffre )
37 l i g n e C l a i r += l e t t r e s [ ( i n d e x C a r a c t e r e C h i f f r e −d i s t a n c e )
%26]
38 else :
152 ANNEXE B. CORRIGÉS DES EXERCICES
39 l i g n e C l a i r += c a r a c t e r e C h i f f r e
40 l i g n e s C l a i r . append ( l i g n e C l a i r )
41 f i c h i e r C l a i r = open ( " c l a i r . t x t " , " wt " )
42 fichierClair . writelines ( lignesClair )
43 f i c h i e r C l a i r . close ()
5. Écrivez un programme permettant de calculer la moyenne d’un étudiant dont les notes sont
consignées dans un fichier CSV. Chaque colonne correspond à une matière. Vous devrez écrire
un fichier JSON consignant ces moyennes ainsi que la moyenne générale. Toutes les notes
et les matières sont au cœfficient 1. Un exemple de fichier CSV est disponible ici : http:
//pastebin.com/raw/szYzyE1k
1 #! / u s r / b i n / env p y t h o n 3
2 import csv
3 import json
4 n o t e s = {}
5 f i c h i e r = open ( " n o t e s . c s v " , " r t " )
6 l e c t e u r C S V = c s v . D i c t R e a d e r ( f i c h i e r , d e l i m i t e r=" ; " , q u o t i n g=c s v .
QUOTE_NONNUMERIC)
7 f o r l i g n e in lecteurCSV :
8 f o r matiere in l i g n e . keys () :
9 i f l i g n e [ m a t i e r e ] != ’ ’ :
10 i f ma tie re not i n notes . keys ( ) :
11 notes [ matiere ] = [ l i g n e [ matiere ] ]
12 else :
13 n o t e s [ m a t i e r e ] . append ( l i g n e [ m a t i e r e ] )
14 f i c h i e r . close ()
15 moyennes = {}
16 moyenneGenerale = 0
17 f o r matiere , notesMatiere in notes . items () :
18 moyennes [ m a t i e r e ] = sum ( n o t e s M a t i e r e ) / l e n ( n o t e s M a t i e r e )
19 m o y e n n e G e n e r a l e += moyennes [ m a t i e r e ]
20 m o y e n n e G e n e r a l e = m o y e n n e G e n e r a l e / l e n ( moyennes . k e y s ( ) )
21 moyennes [ " Moyenne g é n é r a l e " ] = m o y e n n e G e n e r a l e
22 f i c h i e r M o y e n n e s = open ( " moyennes . j s o n " , " wt " )
23 f i c h i e r M o y e n n e s . w r i t e ( j s o n . dumps ( moyennes ) )
24 fichierMoyennes . close ()
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 import csv
4 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " u n i v e r s i t e . db " )
5 c u r s e u r = baseDeDonnees . c u r s o r ( )
6 c u r s e u r . e x e c u t e ( "CREATE TABLE E t u d i a n t s ( i d E t u d i a n t INTEGER
PRIMARY KEY AUTOINCREMENT, nom TEXT NOT NULL , prenom TEXT NOT
NULL , a d r e s s e TEXT, cp TEXT, v i l l e TEXT, t e l F i x e TEXT,
t e l P o r t a b l e TEXT) ; " )
7 c u r s e u r . e x e c u t e ( "CREATE TABLE E n s e i g n a n t s ( i d E n s e i g n a n t INTEGER
PRIMARY KEY AUTOINCREMENT, nom TEXT NOT NULL , prenom TEXT NOT
NULL , a d r e s s e TEXT, cp TEXT, v i l l e TEXT, t e l F i x e TEXT,
t e l P o r t a b l e TEXT) ; " )
8 c u r s e u r . e x e c u t e ( "CREATE TABLE M a t i e r e s ( c o d e M a t i e r e TEXT PRIMARY
KEY , s a l l e TEXT NOT NULL , i d E n s e i g n a n t TEXT NOT NULL ,
FOREIGN KEY ( i d E n s e i g n a n t ) REFERENCES E n s e i g n a n t s (
idEnseignant ) ) ; ")
9 c u r s e u r . e x e c u t e ( "CREATE TABLE I n s c r i p t i o n s ( i d I n s c r i p t i o n
INTEGER PRIMARY KEY AUTOINCREMENT, i d E t u d i a n t INTEGER NOT
NULL , c o d e M a t i e r e TEXT NOT NULL , FOREIGN KEY ( i d E t u d i a n t )
REFERENCES E t u d i a n t s ( i d E t u d i a n t ) , FOREIGN KEY ( c o d e M a t i e r e )
REFERENCES M a t i e r e s ( c o d e M a t i e r e ) ) ; " )
10 c u r s e u r . e x e c u t e ( "CREATE TABLE R e s u l t a t s ( i d R e s u l t a t INTEGER
PRIMARY KEY AUTOINCREMENT, i d I n s c r i p t i o n INTEGER NOT NULL ,
n o t e REAL , FOREIGN KEY ( i d I n s c r i p t i o n ) REFERENCES
Inscriptions ( idInscription )) ;")
11 f i c h i e r E t u d i a n t s = open ( ’ e t u d i a n t s . c s v ’ , ’ r t ’ )
12 CSVEtudiant = c s v . D i c t R e a d e r ( f i c h i e r E t u d i a n t s , d e l i m i t e r=" ; " )
13 f o r l i g n e i n CSVEtudiant :
14 c u r s e u r . e x e c u t e ( " INSERT INTO E t u d i a n t s ( i d E t u d i a n t , nom ,
prenom , a d r e s s e , cp , v i l l e , t e l F i x e , t e l P o r t a b l e ) VALUES
( : NumeroEtudiant , : Nom, : Prenom , : A d r e s s e , : C o d e P o s t a l , :
V i l l e , : TelephoneFixe , : TelephonePortable ) " , l i g n e )
15 f i c h i e r E t u d i a n t s . close ()
16 f i c h i e r E n s e i g n a n t s = open ( ’ e n s e i g n a n t s . c s v ’ , ’ r t ’ )
17 C S V E n s e i g n a n t s = c s v . D i c t R e a d e r ( f i c h i e r E n s e i g n a n t s , d e l i m i t e r=" ;
")
18 f o r l i g n e i n CSVEnseignants :
19 c u r s e u r . e x e c u t e ( " INSERT INTO E n s e i g n a n t s ( i d E n s e i g n a n t , nom ,
prenom , a d r e s s e , cp , v i l l e , t e l F i x e , t e l P o r t a b l e ) VALUES
( : NumeroEnseignant , : Nom, : Prenom , : A d r e s s e , : C o d e P o s t a l
, : V i l l e , : TelephoneFixe , : TelephonePortable ) " , l i g n e )
20 fichierEnseignants . close ()
154 ANNEXE B. CORRIGÉS DES EXERCICES
21 f i c h i e r M a t i e r e s = open ( ’ m a t i e r e s . c s v ’ , ’ r t ’ )
22 CSVMatieres = c s v . D i c t R e a d e r ( f i c h i e r M a t i e r e s , d e l i m i t e r=" ; " )
23 f o r l i g n e i n CSVMatieres :
24 c u r s e u r . e x e c u t e ( " INSERT INTO M a t i e r e s ( c o d e M a t i e r e , s a l l e ,
i d E n s e i g n a n t ) VALUES ( : Cod eMa tie re , : S a l l e , :
NumeroEnseignant ) " , l i g n e )
25 f i c h i e r M a t i e r e s . c l o s e ( )
26 f i c h i e r I n s c r i p t i o n s = open ( ’ i n s c r i p t i o n s . c s v ’ , ’ r t ’ )
27 C S V I n s c r i p t i o n s = c s v . D i c t R e a d e r ( f i c h i e r I n s c r i p t i o n s , d e l i m i t e r=
";")
28 f o r l i g n e i n C S V I n s c r i p t i o n s :
29 c u r s e u r . e x e c u t e ( " INSERT INTO I n s c r i p t i o n s ( i d I n s c r i p t i o n ,
i d E t u d i a n t , c o d e M a t i e r e ) VALUES ( : N u m e r o I n s c r i p t i o n , :
NumeroEtudiant , : C o d e M a t i e r e ) " , l i g n e )
30 f i c h i e r I n s c r i p t i o n s . c l o s e ( )
31 f i c h i e r R e s u l t a t s = open ( ’ r e s u l t a t s . c s v ’ , ’ r t ’ )
32 C S V R e s u l t a t s = c s v . D i c t R e a d e r ( f i c h i e r R e s u l t a t s , d e l i m i t e r=" ; " )
33 f o r l i g n e i n C S V R e s u l t a t s :
34 c u r s e u r . e x e c u t e ( " INSERT INTO R e s u l t a t s ( i d R e s u l t a t ,
i d I n s c r i p t i o n , n o t e ) VALUES ( : N u m e r o R e s u l t a t , :
N u m e r o I n s c r i p t i o n , : Note ) " , l i g n e )
35 baseDeDonnees . commit ( )
36 f i c h i e r R e s u l t a t s . c l o s e ( )
37 baseDeDonnees . c l o s e ( )
2. Écrivez un programme permettant de générer des statistiques pour l’université au format JSON
dont nous stockerons les moyennes par matière, la moyenne maximale et minimale par matière,
le nombre d’étudiants inscrits par matière, la moyenne de toutes les matières et le nombre
d’étudiants par département (les deux premiers nombres du code postal).
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 import json
4 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " u n i v e r s i t e . db " )
5 c u r s e u r = baseDeDonnees . c u r s o r ( )
6 def executerRequete ( requete ) :
7 # Ex é c u t e l a r e q u ê t e e t s t o c k e l e r é s u l t a t s o u s l a f o r m e d ’
un d i c t i o n n a i r e d on t l a c l é e s t l a p r e m i è r e c o l o n n e e t l a
donn é e s e s t l ’ a r r o n d i à deux d é c i m a l e s de l a d e u x i ème
colonne .
8 d o n n e e s = {}
9 curseur . execute ( requete )
10 for ligne in curseur . f e t c h a l l () :
11 donnees [ l i g n e [ 0 ] ] = round ( l i g n e [ 1 ] , 2 )
B.6. INTERAGIR AVEC LES BASES DE DONNÉES 155
12 r e t u r n ( donnees )
13 m o y e n n e M a t i e r e = e x e c u t e r R e q u e t e ( "SELECT c o d e M a t i e r e , AVG( n o t e )
FROM R e s u l t a t s JOIN I n s c r i p t i o n s ON R e s u l t a t s . i d I n s c r i p t i o n
= I n s c r i p t i o n s . i d I n s c r i p t i o n GROUP BY c o d e M a t i e r e ; " )
14 moyenneMax = e x e c u t e r R e q u e t e ( "SELECT c o d e M a t i e r e , max ( moyenne )
FROM ( SELECT c o d e M a t i e r e , i d E t u d i a n t , AVG( n o t e ) AS moyenne
FROM R e s u l t a t s JOIN I n s c r i p t i o n s ON R e s u l t a t s . i d I n s c r i p t i o n =
I n s c r i p t i o n s . i d I n s c r i p t i o n GROUP BY c o d e M a t i e r e , i d E t u d i a n t
ORDER BY i d E t u d i a n t ) GROUP BY c o d e M a t i e r e ; " )
15 moyenneMin = e x e c u t e r R e q u e t e ( "SELECT c o d e M a t i e r e , min ( moyenne )
FROM ( SELECT c o d e M a t i e r e , i d E t u d i a n t , AVG( n o t e ) AS moyenne
FROM R e s u l t a t s JOIN I n s c r i p t i o n s ON R e s u l t a t s . i d I n s c r i p t i o n =
I n s c r i p t i o n s . i d I n s c r i p t i o n GROUP BY c o d e M a t i e r e , i d E t u d i a n t
ORDER BY i d E t u d i a n t ) GROUP BY c o d e M a t i e r e ; " )
16 n b E t u d i a n t s = e x e c u t e r R e q u e t e ( "SELECT c o d e M a t i e r e , c o u n t (
i d E t u d i a n t ) AS n b E t u d i a n t FROM I n s c r i p t i o n s GROUP BY
codeMatiere ; " )
17 c u r s e u r . e x e c u t e ( "SELECT AVG( n o t e ) FROM R e s u l t a t s ; " )
18 m o y e n neT ot ale = r o u n d ( c u r s e u r . f e t c h o n e ( ) [ 0 ] , 2 )
19 n b E t u d i a n t s P a r D e p a r t e m e n t = e x e c u t e r R e q u e t e ( "SELECT d e p a r t e m e n t ,
COUNT( i d E t u d i a n t ) FROM ( SELECT i d E t u d i a n t , SUBSTR( cp , 1 , 2 )
AS d e p a r t e m e n t FROM E t u d i a n t s ) GROUP BY d e p a r t e m e n t ; " )
20 d o n n e e s = { " m o y e n n e M a t i e r e " : moyenneMatiere , " moyenneMax " :
moyenneMax , " moyenneMin " : moyenneMin , " n b E t u d i a n t s " :
n b E t u d i a n t s , " mo ye nne Tot al e " : moyenneTotale , "
nbEtudiantsParDepartement " : nbEtudiantsParDepartement }
21 f i c h i e r = open ( " s t a t i s t i q u e s . j s o n " , " wt " )
22 f i c h i e r . w r i t e ( j s o n . dumps ( d o n n e e s ) )
23 f i c h i e r . c l o s e ( )
24 baseDeDonnees . c l o s e ( )
3. Écrivez un programme permettant de générer un bulletin de notes par étudiant sous la forme
d’un courrier stocké dans un fichier texte individuel. Chaque fichier aura pour nom le nom et
le prénom de l’étudiant, séparés par un trait d’union (-) et pour extension .txt et sera stocké
dans un dossier créé pour cela.
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 from o s i m p o r t m k d i r
4 mkdir ( ’ c o u r r i e r s E t u d i a n t s ’ )
5 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " u n i v e r s i t e . db " )
6 c u r s e u r = baseDeDonnees . c u r s o r ( )
7 c u r s e u r . e x e c u t e ( "SELECT i d E t u d i a n t , nom , prenom , a d r e s s e , cp ,
v i l l e FROM E t u d i a n t s ; " )
156 ANNEXE B. CORRIGÉS DES EXERCICES
8 etudiants = curseur . f e t c h a l l ()
9 for etudiant in etudiants :
10 notes = [ ]
11 i d E t u d i a n t , nom , prenom , a d r e s s e , cp , v i l l e = e t u d i a n t # On
é c l a t e l e t u p l e en v a r i a b l e s i n t e l l i g i b l e s .
12 n o m F i c h i e r = nom + "−" + prenom + " . t x t "
13 f i c h i e r R e s u l t a t s = open ( " c o u r r i e r s E t u d i a n t s / " + n o m F i c h i e r ,
’ wt ’ )
14 f i c h i e r R e s u l t a t s . w r i t e ( " U n i v e r s i t é C l a u d e Chappe \ n15 a v e n u e
de M o u l i n c o u r b e \ n28094 C l a i r e c o m b e \n " )
15 f i c h i e r R e s u l t a t s . w r i t e ( " \ t \ t \ t \ t \ t \ t \ t \ t " + prenom + " " +
nom +" \n " )
16 f i c h i e r R e s u l t a t s . w r i t e ( " \ t \ t \ t \ t \ t \ t \ t \ t " + a d r e s s e +" \n " )
17 f i c h i e r R e s u l t a t s . w r i t e ( " \ t \ t \ t \ t \ t \ t \ t \ t " + cp + " " + v i l l e
+" \n " )
18 f i c h i e r R e s u l t a t s . w r i t e ( "Madame , Monsieur , \ n V e u i l l e z t r o u v e r
da ns l e r é c a p i t u l a t i f c i −d e s s o u s l e s r é s u l t a t s de v o s
examens . \ n " )
19 f i c h i e r R e s u l t a t s . w r i t e ( " M a t i e r e \ t \ t \ t \ tMoyenne \n " )
20 c u r s e u r . e x e c u t e ( "SELECT c o d e M a t i e r e , AVG( n o t e ) AS moyenne
FROM R e s u l t a t s JOIN I n s c r i p t i o n s ON R e s u l t a t s .
i d I n s c r i p t i o n = I n s c r i p t i o n s . i d I n s c r i p t i o n WHERE
I n s c r i p t i o n s . i d E t u d i a n t = ? GROUP BY c o d e M a t i e r e ; " , ( s t r (
idEtudiant ) ,) )
21 for ligne in curseur . f e t c h a l l () :
22 f i c h i e r R e s u l t a t s . w r i t e ( l i g n e [ 0 ] + "\ t \ t \ t \ t " + s t r ( round
( l i g n e [ 1 ] , 2 ) ) + " \n " )
23 n o t e s . append ( r o u n d ( l i g n e [ 1 ] , 2 ) )
24 moyenne = sum ( n o t e s ) / l e n ( n o t e s )
25 f i c h i e r R e s u l t a t s . w r i t e ( " Moyenne g é n é r a l e \ t " + s t r ( r o u n d (
moyenne , 2 ) ) + " \n " )
26 f i c h i e r R e s u l t a t s . w r i t e ( " Ce document c o n s t i t u e l e s r é s u l t a t s
o f f i c i e l s . Pour t o u t e c o n t e s t a t i o n , c o n t a c t e z l e s e r v i c e
s c o l a r i t é . \n " )
27 f i c h i e r R e s u l t a t s . close ()
28 baseDeDonnees . c l o s e ( )
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " u n i v e r s i t e . db " )
4 c u r s e u r = baseDeDonnees . c u r s o r ( )
B.6. INTERAGIR AVEC LES BASES DE DONNÉES 157
5 matieres = [ ]
6 c u r s e u r . e x e c u t e ( "SELECT c o d e M a t i e r e FROM M a t i e r e s ; " )
7 for ligne in curseur . f e t c h a l l () :
8 m a t i e r e s . append ( l i g n e [ 0 ] )
9 a c t i f =True
10 while a c t i f :
11 nom = i n p u t ( " E n t r e z l e nom du n o u v e l é t u d i a n t : " )
12 prenom = i n p u t ( " E n t r e z l e p r énom du n o u v e l é t u d i a n t : " )
13 a d r e s s e = i n p u t ( " E n t r e z l ’ a d r e s s e du n o u v e l é t u d i a n t : " )
14 cp = i n p u t ( " E n t r e z l e code p o s t a l du n o u v e l é t u d i a n t : " )
15 v i l l e = i n p u t ( " E n t r e z l a v i l l e du n o u v e l é t u d i a n t : " )
16 t e l F i x e = i n p u t ( " E n t r e z l e t é l é phone f i x e du n o u v e l é t u d i a n t
: ")
17 t e l P o r t a b l e = i n p u t ( " E n t r e z l e t é l é phone p o r t a b l e du n o u v e l
é tudiant : ")
18 c u r s e u r . e x e c u t e ( " INSERT INTO E t u d i a n t s ( nom , prenom , a d r e s s e
, cp , v i l l e , t e l F i x e , t e l P o r t a b l e ) VALUES ( ? , ? , ? , ? , ? , ? , ? )
" , ( nom , prenom , a d r e s s e , cp , v i l l e , t e l F i x e , t e l P o r t a b l e
))
19 baseDeDonnees . commit ( )
20 idEtudiant = curseur . lastrowid
21 m a t i e r e A c t i f = True
22 while matiereActif :
23 m a t i e r e = i n p u t ( " E n t r e z l e code de m a t i è r e d ans l a q u e l l e
i n s c r i r e l ’ é t u d i a n t ( l a i s s e z v i d e pour a r r ê ter ,
tapez ’? ’ pour a f f i c h e r l a l i s t e ) : " )
24 i f m a t i e r e == " " :
25 matiereActif = False
26 e l i f m a t i e r e == " ? " :
27 for ligne in matieres :
28 print ( ligne )
29 e l i f matiere . upper () i n m a t i e r e s :
30 c u r s e u r . e x e c u t e ( " INSERT INTO I n s c r i p t i o n s (
i d E t u d i a n t , c o d e M a t i e r e ) VALUES ( ? , ? ) " , (
idEtudiant , matiere ) )
31 baseDeDonnees . commit ( )
32 else :
33 p r i n t ( " La m a t i è r e n ’ e x i s t e p a s . " )
34 r e p o n s e = i n p u t ( " Voulez −v o u s s a i s i r un n o u v e l é t u d i a n t (O/N)
? ")
35 a c t i f = False
36 i f r e p o n s e . u p p e r ( ) == "O" :
37 a c t i f = True
158 ANNEXE B. CORRIGÉS DES EXERCICES
38 baseDeDonnees . c l o s e ( )
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " u n i v e r s i t e . db " )
4 c u r s e u r = baseDeDonnees . c u r s o r ( )
5 matieres = [ ]
6 c u r s e u r . e x e c u t e ( "SELECT c o d e M a t i e r e FROM M a t i e r e s ; " )
7 for ligne in curseur . f e t c h a l l () :
8 m a t i e r e s . append ( l i g n e [ 0 ] )
9 a c t i f =True
10 while a c t i f :
11 m a t i e r e = i n p u t ( " E n t r e z l e code de m a t i è r e de l ’ examen (
l a i s s e z v i d e pour a r r ê ter , tapez ’? ’ pour a f f i c h e r l a
liste ) : ")
12 i f m a t i e r e == " " :
13 matiereActif = False
14 e l i f m a t i e r e == " ? " :
15 for ligne in matieres :
16 print ( ligne )
17 e l i f matiere . upper () i n m a t i e r e s :
18 c u r s e u r . e x e c u t e ( "SELECT i d I n s c r i p t i o n , nom , prenom FROM
I n s c r i p t i o n s JOIN E t u d i a n t s ON I n s c r i p t i o n s .
i d E t u d i a n t = E t u d i a n t s . i d E t u d i a n t WHERE I n s c r i p t i o n s .
codeMatiere = ?; " , ( matiere , ) )
19 e t u d i a n t s I n s c r i t s = curseur . f e t c h a l l ()
20 for ligne in etudiantsInscrits :
21 i d I n s c r i p t i o n , nom , prenom = l i g n e
22 note = f l o a t ( input ( " Entrez l a note obtenue par " +
prenom + " " + nom + " : " ) . r e p l a c e ( ’ , ’ , ’ . ’ ) )
23 c u r s e u r . e x e c u t e ( " INSERT INTO R e s u l t a t s (
i d I n s c r i p t i o n , n o t e ) VALUES ( ? , ? ) " , (
i d I n s c r i p t i o n , note ) )
24 r e p o n s e = i n p u t ( " Voulez −v o u s s a i s i r un nouveau r é s u l t a t (O/N
) ? ")
25 a c t i f = False
26 i f r e p o n s e . u p p e r ( ) == "O" :
27 a c t i f = True
28 baseDeDonnees . commit ( )
29 baseDeDonnees . c l o s e ( )
B.7. LA PROGRAMMATION RÉSEAU 159
1. Écrivez un programme permettant de créer sur le serveur une base de données SQLite3 nommée
banque.db et de créer la structure de table adaptée au stockage des données. Importez le
contenu des fichiers CSV dans cette base.
1 #! / u s r / b i n / env p y t h o n 3
2 import s q l i t e 3
3 import csv
4 baseDeDonnees = s q l i t e 3 . c o n n e c t ( " banque . db " )
5 c u r s e u r = baseDeDonnees . c u r s o r ( )
6 c u r s e u r . e x e c u t e ( "CREATE TABLE C l i e n t s ( i d C l i e n t INTEGER PRIMARY
KEY AUTOINCREMENT, nom TEXT NOT NULL , prenom TEXT NOT NULL ,
a d r e s s e TEXT, cp TEXT, v i l l e TEXT, t e l F i x e TEXT, t e l P o r t a b l e
TEXT) ; " )
7 c u r s e u r . e x e c u t e ( "CREATE TABLE Comptes ( idCompte INTEGER PRIMARY
KEY AUTOINCREMENT, i d C l i e n t INTEGER NOT NULL , typeCompte TEXT
NOT NULL , codePIN TEXT NOT NULL , s o l d e REAL , FOREIGN KEY (
i d C l i e n t ) REFERENCES C l i e n t s ( i d C l i e n t ) ) ; " )
8 c u r s e u r . e x e c u t e ( "CREATE TABLE O p e r a t i o n s ( i d O p e r a t i o n INTEGER
PRIMARY KEY AUTOINCREMENT, d a t e O p e r a t i o n TEXT NOT NULL ,
idCompte INTEGER NOT NULL , l i b e l l e O p e r a t i o n TEXT NOT NULL ,
montant REAL , FOREIGN KEY ( idCompte ) REFERENCES Comptes (
idCompte ) ) ; " )
9 f i c h i e r C l i e n t s = open ( ’ c l i e n t s . c s v ’ , ’ r t ’ )
10 C S V C l i e n t s = c s v . D i c t R e a d e r ( f i c h i e r C l i e n t s , d e l i m i t e r=" ; " )
11 f o r l i g n e in CSVClients :
12 c u r s e u r . e x e c u t e ( " INSERT INTO C l i e n t s ( i d C l i e n t , nom , prenom ,
a d r e s s e , cp , v i l l e , t e l F i x e , t e l P o r t a b l e ) VALUES ( :
N u m e r o C l i e n t , : Nom, : Prenom , : A d r e s s e , : C o d e P o s t a l , :
V i l l e , : TelephoneFixe , : TelephonePortable ) " , l i g n e )
13 f i c h i e r C l i e n t s . close ()
14 f i c h i e r C o m p t e s = open ( ’ comptes . c s v ’ , ’ r t ’ )
15 CSVComptes = c s v . D i c t R e a d e r ( f i c h i e r C o m p t e s , d e l i m i t e r=" ; " )
16 f o r l i g n e i n CSVComptes :
17 c u r s e u r . e x e c u t e ( " INSERT INTO Comptes ( idCompte , i d C l i e n t ,
typeCompte , codePIN , s o l d e ) VALUES ( : NumeroCompte , :
N u m e r o C l i e n t , : TypeCompte , : PIN , : S o l d e ) " , l i g n e )
18 fichierComptes . close ()
19 f i c h i e r O p e r a t i o n s = open ( ’ o p e r a t i o n s . c s v ’ , ’ r t ’ )
20 C S V O p e ra ti o ns = c s v . D i c t R e a d e r ( f i c h i e r O p e r a t i o n s , d e l i m i t e r=" ; " )
21 f o r l i g n e i n CS VO p er a ti on s :
160 ANNEXE B. CORRIGÉS DES EXERCICES
31 baseDeDonnees , c u r s e u r = c o n n e x i o n B a s e D e D o n n e e s ( )
32 montant = f l o a t ( montant )
33 s o l d e C o m p t e = s o l d e ( nocompte )
34 i f s o l d e C o m p t e < montant o r montant >= 0 :
35 baseDeDonnees . c l o s e ( )
36 return False
37 else :
38 n o u v e a u S o l d e = s o l d e C o m p t e+montant
39 c u r s e u r . e x e c u t e ( "UPDATE Comptes SET s o l d e = ? WHERE
idCompte = ? " , ( n o u v e a u S o l d e , nocompte ) )
40 c u r s e u r . e x e c u t e ( " INSERT INTO O p e r a t i o n s ( d a t e O p e r a t i o n ,
idCompte , l i b e l l e O p e r a t i o n , montant ) VALUES (DATE( ’NOW
’ ) , ? , ? , ? ) " , ( nocompte , " R e t r a i t " , montant ) )
41 baseDeDonnees . commit ( )
42 baseDeDonnees . c l o s e ( )
43 r e t u r n True
44
45 d e f t r a n s f e r t ( nocompteSource , n o c o m p t e D e s t i n a t i o n , montant ) :
46 #Le montant e s t p o s i t i f
47 baseDeDonnees , c u r s e u r = c o n n e x i o n B a s e D e D o n n e e s ( )
48 montant = f l o a t ( montant )
49 s o l d e C o m p t e S o u r c e = s o l d e ( nocom pte Sour ce )
50 i f s o l d e C o m p t e S o u r c e < montant o r montant <= 0 :
51 baseDeDonnees . c l o s e ( )
52 return False
53 else :
54 n o u v e a u S o l d e S o u r c e = s o l d e C o m p t e S o u r c e −montant
55 c u r s e u r . e x e c u t e ( "UPDATE Comptes SET s o l d e = ? WHERE
idCompte = ? " , ( n o u v e a u S o l d e S o u r c e , noc omp teSou rce ) )
56 c u r s e u r . e x e c u t e ( " INSERT INTO O p e r a t i o n s ( d a t e O p e r a t i o n ,
idCompte , l i b e l l e O p e r a t i o n , montant ) VALUES (DATE( ’NOW
’ ) , ? , ? , ? ) " , ( nocompteSource , " V i r e m e n t " , −montant ) )
57 soldeCompteDestination = solde ( nocompteDestination )
58 n o u v e a u S o l d e D e s t i n a t i o n = s o l d e C o m p t e D e s t i n a t i o n+montant
59 c u r s e u r . e x e c u t e ( "UPDATE Comptes SET s o l d e = ? WHERE
idCompte = ? " , ( n o u v e a u S o l d e D e s t i n a t i o n ,
nocompteDestination ) )
60 c u r s e u r . e x e c u t e ( " INSERT INTO O p e r a t i o n s ( d a t e O p e r a t i o n ,
idCompte , l i b e l l e O p e r a t i o n , montant ) VALUES (DATE( ’NOW
’ ) , ? , ? , ? ) " , ( n o c o m p t e D e s t i n a t i o n , " V i r e m e n t " , montant
))
61 baseDeDonnees . commit ( )
62 baseDeDonnees . c l o s e ( )
162 ANNEXE B. CORRIGÉS DES EXERCICES
63 r e t u r n True
64
65 d e f d e p o t ( nocompte , montant ) :
66 #Le montant e s t p o s i t i f
67 baseDeDonnees , c u r s e u r = c o n n e x i o n B a s e D e D o n n e e s ( )
68 montant = f l o a t ( montant )
69 s o l d e C o m p t e = s o l d e ( nocompte )
70 n o u v e a u S o l d e = s o l d e C o m p t e+montant
71 c u r s e u r . e x e c u t e ( "UPDATE Comptes SET s o l d e = ? WHERE idCompte
= ? " , ( n o u v e a u S o l d e , nocompte ) )
72 c u r s e u r . e x e c u t e ( " INSERT INTO O p e r a t i o n s ( d a t e O p e r a t i o n ,
idCompte , l i b e l l e O p e r a t i o n , montant ) VALUES (DATE( ’NOW ’ ) ,
? , ? , ? ) " , ( nocompte , "Dé pô t " , montant ) )
73 baseDeDonnees . commit ( )
74 baseDeDonnees . c l o s e ( )
75 r e t u r n True
76
77 d e f h i s t o r i q u e ( nocompte ) :
78 baseDeDonnees , c u r s e u r = c o n n e x i o n B a s e D e D o n n e e s ( )
79 c u r s e u r . e x e c u t e ( "SELECT d a t e O p e r a t i o n , l i b e l l e O p e r a t i o n ,
montant FROM O p e r a t i o n s WHERE idCompte = ? ORDER BY
d a t e O p e r a t i o n DESC LIMIT 1 0 ; " , ( nocompte , ) )
80 h i s t o r i q u e C S V = " \" d a t e O p e r a t i o n \ " ; \ " l i b e l l e O p e r a t i o n \ " ; \ "
montant \"\ n "
81 for ligne in curseur . f e t c h a l l () :
82 h i s t o r i q u e C S V += " \" " + l i g n e [ 0 ] + " \ " ; \ " " + l i g n e [ 1 ] + "
\ " ; \ " " + s t r ( l i g n e [ 2 ] ) + " \"\ n "
83 return historiqueCSV
84
85 d e f i n s t a n c e S e r v e u r ( c l i e n t , i n f o s C l i e n t ) :
86 adresseIP = infosClient [0]
87 port = s t r ( i n f o s C l i e n t [ 1 ] )
88 p r i n t ( " I n s t a n c e de s e r v e u r p r ê t p o u r " + a d r e s s e I P + " : " +
port )
89 a c t i f = True
90 while a c t i f :
91 message = c l i e n t . r e c v ( 2 5 5 ) . d e c o d e ( " u t f −8" ) . u p p e r ( ) . s p l i t ( "
")
92 pret = False
93 i f message [ 0 ] == "TESTPIN" :
94 i f t e s t p i n ( message [ 1 ] , message [ 2 ] ) :
95 c l i e n t . s e n d ( "TESTPIN OK" . e n c o d e ( " u t f −8" ) )
B.7. LA PROGRAMMATION RÉSEAU 163
Programme distributeur :
164 ANNEXE B. CORRIGÉS DES EXERCICES
1 #! / u s r / b i n / env p y t h o n 3
2 import socket
3 adresseIP = " 127.0.0.1 " # Ici , l e poste l o c a l
4 p o r t = 50000 # Se c o n n e c t e r s u r l e p o r t 50000
5 w h i l e True :
6 c l i e n t = s o c k e t . s o c k e t ( s o c k e t . AF_INET , s o c k e t . SOCK_STREAM)
7 c l i e n t . connect (( adresseIP , port ) )
8 p r i n t ( " B i e n v e n u e dan s l a banque Python " )
9 nocompte = i n p u t ( " E n t r e z v o t r e numé r o de compte : " )
10 p i n = i n p u t ( " E n t r e z v o t r e code PIN : " )
11 c l i e n t . s e n d ( ( "TESTPIN " + nocompte + " " + p i n ) . e n c o d e ( " u t f −8
"))
12 r e p o n s e = c l i e n t . r e c v ( 2 5 5 ) . d e c o d e ( " u t f −8" )
13 i f r e p o n s e == "TESTPIN OK" :
14 p r i n t ( " Bienvenue ! " )
15 p r i n t ( " Opé r a t i o n s : " )
16 p r i n t ( " 1 − Dé pô t " )
17 print ( "2 − Retrait " )
18 print ( "3 − Transfert " )
19 p r i n t ( " 4 − H i s t o r i q u e d e s op é r a t i o n s " )
20 p r i n t ( " 5 − S o l d e du compte " )
21 o p e r a t i o n = i n p u t ( " E n t r e z l ’ op é r a t i o n que v o u s s o u h a i t e z :
")
22 i f o p e r a t i o n == " 1 " :
23 montant = i n p u t ( " E n t r e z l e montant à d é p o s e r : " )
24 c l i e n t . s e n d ( ( "DEPOT " + nocompte + " " + montant ) .
e n c o d e ( " u t f −8" ) )
25 r e p o n s e = c l i e n t . r e c v ( 2 5 5 ) . d e c o d e ( " u t f −8" )
26 p r i n t ( "Dé p o t e f f e c t u é " )
27 e l i f o p e r a t i o n == " 2 " :
28 montant = i n p u t ( " E n t r e z l e montant à r e t i r e r : " )
29 montant = s t r (− f l o a t ( montant ) ) # Le montant d o i t ê t r e
né g a t i f
30 c l i e n t . s e n d ( ( "RETRAIT " + nocompte + " " + montant ) .
e n c o d e ( " u t f −8" ) )
31 r e p o n s e = c l i e n t . r e c v ( 2 5 5 ) . d e c o d e ( " u t f −8" )
32 i f r e p o n s e == "RETRAIT OK" :
33 print (" Retrait effectu é")
34 else :
35 print (" Retrait refus é")
36 e l i f o p e r a t i o n == " 3 " :
37 montant = i n p u t ( " E n t r e z l e montant à t r a n s f e r e r : " )
B.8. MODÉLISATION POUR LA PROGRAMMATION ORIENTÉE OBJET 165
Atome
-nom
-symbole
-numeroAtomique
Cylindre
-hauteur
Cercle
+calculerVolume : float
-rayon
+calculerPerimetre : float
Sphere
+calculerAire : float
+calculerVolume : float
Compte
-solde
Banque -historiqueOperations
58 s c o r e s [ " f u l l " ] = 25
59 isGrandeSuite = False
60 i f ( 1 i n d e s and 2 i n d e s and 3 i n d e s and 4 i n d e s and 5 i n
d e s ) o r ( 2 i n d e s and 3 i n d e s and 4 i n d e s and 5 i n d e s
and 6 i n d e s ) :
61 i s G r a n d e S u i t e = True
62 i f isGrandeSuite :
63 s c o r e s [ " g r a n d e S u i t e " ] = 40
64 isPetiteSuite = False
65 i f ( 1 i n d e s and 2 i n d e s and 3 i n d e s and 4 i n d e s ) o r ( 2 i n
d e s and 3 i n d e s and 4 i n d e s and 5 i n d e s ) o r ( 3 i n d e s
and 4 i n d e s and 5 i n d e s and 6 i n d e s ) :
66 i s P e t i t e S u i t e = True
67 if isPetiteSuite :
68 s c o r e s [ " p e t i t e S u i t e " ] = 30
69 i f 3 in occurences . values () :
70 s c o r e s [ " b r e l a n " ] = sum ( d e s )
71 s c o r e s [ " c h a n c e " ] = sum ( d e s )
72 return ( scores )
73 c l a s s Joueur ( o b j e c t ) :
74 d e f __init__ ( s e l f , nom , p l a t e a u ) :
75 s e l f . __nom = nom
76 s e l f . plateau = plateau
77 s e l f . _ _ s c o r e s = { " a s " : −1 , " deux " : −1 , " t r o i s " : −1 , " q u a t r e " : −1 ,
" c i n q " : −1 , " s i x " : −1 , " p r i m e " : 0 , " b r e l a n " : −1 , " p e t i t e S u i t e "
: −1 , " g r a n d e S u i t e " : −1 , " f u l l " : −1 , " c a r r e " : −1 , " y a h t z e e " : −1 ,
" c h a n c e " : −1}
78 def lireNom ( s e l f ) :
79 r e t u r n ( s e l f . __nom)
80 def l i r e S c o r e s ( s e l f ) :
81 r e t u r n ( s e l f . __scores )
82 def calculerTotalGeneral ( s e l f ) :
83 totalGeneral = 0
84 f o r s c o r e i n s e l f . __scores . v a l u e s () :
85 i f s c o r e == −1:
86 score = 0
87 t o t a l G e n e r a l += s c o r e
88 return ( totalGeneral )
89 def a f f i c h e r S c o r e s ( s e l f ) :
90 # Permet un a f f i c h a g e p l u s é l é g a n t
91 totalPartieInferieure = 0
92 totalPartieSuperieure = 0
93 p r i n t ( " ∗ ∗ ∗ S c o r e s de " + s e l f . __nom + " ∗ ∗ ∗ " )
B.9. LA PROGRAMMATION ORIENTÉE OBJET 169
94 p r i n t ( "= P a r t i e i n f é r i e u r e =" )
95 for etiquette in p a r t i e I n f e r i e u r e :
96 s c o r e = s e l f . __scores [ e t i q u e t t e [ " s c o r e " ] ]
97 i f s c o r e == −1:
98 score = 0
99 p r i n t ( e t i q u e t t e [ "nom" ] + " : " + s t r ( s c o r e ) )
100 t o t a l P a r t i e I n f e r i e u r e += s c o r e
101 p r i n t ( " Total p a r t i e i n f é r i e u r e : " + s t r (
totalPartieInferieure ))
102 p r i n t ( "= P a r t i e sup é r i e u r e =" )
103 for etiquette in partieSuperieure :
104 s c o r e = s e l f . __scores [ e t i q u e t t e [ " s c o r e " ] ]
105 i f s c o r e == −1:
106 score = 0
107 p r i n t ( e t i q u e t t e [ "nom" ] + " : " + s t r ( s c o r e ) )
108 t o t a l P a r t i e S u p e r i e u r e += s c o r e
109 p r i n t ( " T o t a l p a r t i e sup é r i e u r e : " + s t r (
totalPartieSuperieure ))
110 p r i n t ( " Total general : " + s t r ( s e l f . c a l c u l e r T o t a l G e n e r a l () ) )
111 def e n r e g i s t r e r S c o r e ( s e l f , typeScore , score ) :
112 s e l f . __scores [ typeScore ] = s c o r e
113 totalPartieInferieure = 0
114 s e l f . __scores [ " prime " ] = 0
115 for etiquette in p a r t i e I n f e r i e u r e :
116 t o t a l P a r t i e I n f e r i e u r e += s e l f . _ _ s c o r e s [ e t i q u e t t e [ " s c o r e " ] ]
117 i f t o t a l P a r t i e I n f e r i e u r e >= 6 3 :
118 s e l f . _ _ s c o r e s [ " p r i m e " ] = 35
119 c l a s s JoueurHumain ( J o u e u r ) :
120 d e f __init__ ( s e l f , p l a t e a u ) :
121 nom = i n p u t ( " E n t r e z v o t r e nom : " )
122 J o u e u r . __init__ ( s e l f , nom , p l a t e a u )
123 def jouer ( s e l f ) :
124 s e l f . plateau . melangerPlateau ()
125 tiragesRestants = 2
126 while tiragesRestants > 0:
127 p r i n t ( " Votre t i r a g e : " )
128 s e l f . plateau . afficherPlateau ()
129 r e p o n s e = i n p u t ( " Voulez −v o u s r e t i r e r d e s d é s ( " + s t r (
t i r a g e s R e s t a n t s ) + " t i r a g e s r e s t a n t s ) (O/N) : " ) . u p p e r
()
130 i f r e p o n s e == "O" :
131 f o r noDe , de i n e n u m e r a t e ( s e l f . p l a t e a u . l i r e ( ) ) :
132 p r i n t ( "Dé no " + s t r ( noDe +1) + " : " + s t r ( de ) )
170 ANNEXE B. CORRIGÉS DES EXERCICES
1 #! / u s r / b i n / env p y t h o n 3
2 import sys
3 from P y S i d e 2 i m p o r t QtCore , QtGui , QtWidgets
4 import s q l i t e 3
5 import os
6 import time
7 f i c h i e r B a s e D e D o n n e e s = " t a r i f i c a t i o n . db "
8 i f o s . p a t h . i s f i l e ( f i c h i e r B a s e D e D o n n e e s ) == F a l s e :
9 baseDeDonnees = s q l i t e 3 . c o n n e c t ( f i c h i e r B a s e D e D o n n e e s )
10 c u r s e u r = baseDeDonnees . c u r s o r ( )
11 c u r s e u r . e x e c u t e ( "CREATE TABLE P r e s t a t i o n s ( i d INTEGER PRIMARY KEY
AUTOINCREMENT, c a t e g o r i e TEXT NOT NULL , l i b e l l e TEXT NOT NULL
, p r i x U n i t a i r e REAL NOT NULL , u n i t e TEXT NOT NULL) " )
12 baseDeDonnees . commit ( )
13 c u r s e u r . e x e c u t e ( "CREATE TABLE E s t i m a t i o n s ( i d INTEGER PRIMARY KEY
AUTOINCREMENT, n o m C l i e n t TEXT NOT NULL , p r e n o m C l i e n t TEXT NOT
NULL , a d r e s s e TEXT NOT NULL , c o d e P o s t a l TEXT NOT NULL , v i l l e
TEXT NOT NULL , t e l e p h o n e TEXT, c o u r r i e l TEXT, n o m C h a n t i e r TEXT
)")
14 baseDeDonnees . commit ( )
15 c u r s e u r . e x e c u t e ( "CREATE TABLE L i g n e s E s t i m a t i o n s ( i d INTEGER
PRIMARY KEY AUTOINCREMENT, i d E s t i m a t i o n INTEGER NOT NULL ,
i d P r e s t a t i o n INTEGER NOT NULL , o r d r e INTEGER , q u a n t i t e REAL
NOT NULL , tauxTVA REAL) " )
16 baseDeDonnees . commit ( )
17 baseDeDonnees = s q l i t e 3 . c o n n e c t ( f i c h i e r B a s e D e D o n n e e s )
18 c u r s e u r = baseDeDonnees . c u r s o r ( )
19 c l a s s E d i t i o n P r e s t a t i o n ( QtWidgets . QDialog ) :
20 d e f __init__ ( s e l f , i d P r e s t a t i o n=None , p a r e n t=None ) :
21 QtWidgets . QDialog . __init__ ( s e l f , p a r e n t )
22 s e l f . __idPrestation = idPrestation
23 s e l f . s e t W i n d o w T i t l e ( "É d i t e r une p r e s t a t i o n " )
24 s e l f . s e t W i n d o w I c o n ( QtGui . QIcon ( " / u s r / s h a r e / i c o n s / Humanity /
a c t i o n s /24/ s t o c k _ e d i t . s v g " ) )
25 s e l f . _ _ c a t e g o r i e = QtWidgets . QComboBox ( )
B.10. LES INTERFACES GRAPHIQUES 173
169 s e l f . __prestations = [ ]
170 s e l f . __lignesChiffrage = [ ]
171 s e l f . _ _ l i s t e P r e s t a t i o n s = QtWidgets . Q L i s t W i d g e t ( )
172 s e l f . _ _ b a r r e R e c h e r c h e = QtWidgets . Q L i n e E d i t ( " " )
173 s e l f . _ _ c r e e r P r e s t a t i o n = QtWidgets . QPushButton ( " Cr é e r une
prestation ")
174 s e l f . _ _ c r e e r P r e s t a t i o n . s e t I c o n ( QtGui . QIcon ( " / u s r / s h a r e / i c o n s /
Humanity / a c t i o n s /24/ e d i t −add . s v g " ) )
175 s e l f . _ _ m o d i f i e r P r e s t a t i o n = QtWidgets . QPushButton ( " M o d i f i e r
une p r e s t a t i o n " )
176 s e l f . _ _ m o d i f i e r P r e s t a t i o n . s e t I c o n ( QtGui . QIcon ( " / u s r / s h a r e /
i c o n s / Humanity / a c t i o n s /24/ s t o c k _ e d i t . s v g " ) )
177 s e l f . _ _ s u p p r i m e r P r e s t a t i o n = QtWidgets . QPushButton ( " S u p p r i m e r
une p r e s t a t i o n " )
178 s e l f . _ _ s u p p r i m e r P r e s t a t i o n . s e t I c o n ( QtGui . QIcon ( " / u s r / s h a r e /
i c o n s / Humanity / a c t i o n s /24/ s t o c k _ d e l e t e . s v g " ) )
179 s e l f . __prixUnitaire = 0.0
180 s e l f . __unite = " "
181 s e l f . __prixHT = 0 . 0
182 s e l f . __prixTVA = 0 . 0
183 s e l f . __prixTTC = 0 . 0
184 s e l f . _ _ p r i x U n i t a i r e L a b e l = QtWidgets . QLabel ( " P r i x u n i t a i r e :
0 , 0 0e" )
185 s e l f . _ _ q u a n t i t e L a b e l = QtWidgets . QLabel ( " Q u a n t i t é : " )
186 s e l f . _ _ q u a n t i t e = QtWidgets . QDoubleSpinBox ( )
187 s e l f . _ _ t v a L a b e l = QtWidgets . QLabel ( "TVA : " )
188 s e l f . __tva = QtWidgets . QDoubleSpinBox ( )
189 s e l f . __tva . s e t S u f f i x ( "%" )
190 s e l f . _ _ t o t a u x L a b e l = QtWidgets . QLabel ( "HT : 0 , 0 0 e\nTVA : 0 , 0 0
e\nTTC : 0 , 0 0 e" )
191 s e l f . _ _ a j o u t e r P r e s t a t i o n = QtWidgets . QPushButton ( " A j o u t e r l a
prestation ")
192 s e l f . _ _ a j o u t e r P r e s t a t i o n . s e t I c o n ( QtGui . QIcon ( " / u s r / s h a r e / i c o n s
/ Humanity / a c t i o n s /24/ d i a l o g −a p p l y . s v g " ) )
193 s e l f . _ _ p r e s t a t i o n L a y o u t = QtWidgets . QVBoxLayout ( )
194 s e l f . _ _ l i s t e C a t e g o r i e s L a y o u t = QtWidgets . QFormLayout ( )
195 s e l f . _ _ l i s t e C a t e g o r i e s L a y o u t . addRow ( " Cat é g o r i e : " , s e l f .
__listeCategories )
196 s e l f . __prestationLayout . addLayout ( s e l f . _ _ l i s t e C a t e g o r i e s L a y o u t
)
197 s e l f . _ _ a c t i o n P r e s t a t i o n L a y o u t = QtWidgets . QHBoxLayout ( )
198 s e l f . _ _ a c t i o n P r e s t a t i o n L a y o u t . addWidget ( s e l f . _ _ c r e e r P r e s t a t i o n
)
178 ANNEXE B. CORRIGÉS DES EXERCICES
199 s e l f . _ _ a c t i o n P r e s t a t i o n L a y o u t . addWidget ( s e l f .
__modifierPrestation )
200 s e l f . _ _ a c t i o n P r e s t a t i o n L a y o u t . addWidget ( s e l f .
__supprimerPrestation )
201 s e l f . __prestationLayout . addLayout ( s e l f .
__actionPrestationLayout )
202 s e l f . _ _ b a r r e R e c h e r c h e L a y o u t = QtWidgets . QFormLayout ( )
203 s e l f . _ _ b a r r e R e c h e r c h e L a y o u t . addRow ( " R e c h e r c h e : " , s e l f .
__barreRecherche )
204 s e l f . __prestationLayout . addLayout ( s e l f . __barreRechercheLayout )
205 s e l f . _ _ p r e s t a t i o n L a y o u t . addWidget ( s e l f . _ _ l i s t e P r e s t a t i o n s )
206 s e l f . __quantiteTVALayout = QtWidgets . QHBoxLayout ( )
207 s e l f . __quantiteTVALayout . addWidget ( s e l f . _ _ p r i x U n i t a i r e L a b e l )
208 s e l f . __quantiteTVALayout . a d d S t r e t c h ( )
209 s e l f . __quantiteTVALayout . addWidget ( s e l f . _ _ q u a n t i t e L a b e l )
210 s e l f . __quantiteTVALayout . addWidget ( s e l f . _ _ q u a n t i t e )
211 s e l f . __quantiteTVALayout . a d d S t r e t c h ( )
212 s e l f . __quantiteTVALayout . addWidget ( s e l f . _ _ t v a L a b e l )
213 s e l f . __quantiteTVALayout . addWidget ( s e l f . __tva )
214 s e l f . _ _ p r e s t a t i o n L a y o u t . a d d L a y o u t ( s e l f . __quantiteTVALayout )
215 s e l f . _ _ p r e s t a t i o n L a y o u t . addWidget ( s e l f . _ _ t o t a u x L a b e l )
216 s e l f . _ _ p r e s t a t i o n L a y o u t . addWidget ( s e l f . _ _ a j o u t e r P r e s t a t i o n )
217 s e l f . __nomClient = QtWidgets . Q L i n e E d i t ( " " )
218 s e l f . _ _ p r e n o m C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
219 s e l f . _ _ a d r e s s e C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
220 s e l f . _ _ c p C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
221 s e l f . _ _ c p C l i e n t . s e t I n p u t M a s k ( " 0 0 0 0 0 ;_" )
222 s e l f . _ _ v i l l e C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
223 s e l f . _ _ t e l e p h o n e C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
224 s e l f . _ _ t e l e p h o n e C l i e n t . s e t I n p u t M a s k ( " 00 00 00 00 0 0 ;_" )
225 s e l f . _ _ c o u r r i e l C l i e n t = QtWidgets . Q L i n e E d i t ( " " )
226 s e l f . __nomChantier = QtWidgets . Q L i n e E d i t ( " " )
227 s e l f . _ _ n o m C l i e n t L a b e l = QtWidgets . QLabel ( "Nom : " )
228 s e l f . _ _ p r e n o m C l i e n t L a b e l = QtWidgets . QLabel ( " Pr énom : " )
229 s e l f . _ _ a d r e s s e C l i e n t L a b e l = QtWidgets . QLabel ( " A d r e s s e : " )
230 s e l f . _ _ c p C l i e n t L a b e l = QtWidgets . QLabel ( " Code p o s t a l : " )
231 s e l f . _ _ v i l l e C l i e n t L a b e l = QtWidgets . QLabel ( " V i l l e : " )
232 s e l f . _ _ t e l e p h o n e C l i e n t L a b e l = QtWidgets . QLabel ( "Té l é phone : " )
233 s e l f . _ _ c o u r r i e l C l i e n t L a b e l = QtWidgets . QLabel ( " C o u r r i e l : " )
234 s e l f . __nomChantierLabel = QtWidgets . QLabel ( "Nom du c h a n t i e r : "
)
235 s e l f . _ _ o u v r i r = QtWidgets . QPushButton ( " O u v r i r " )
B.10. LES INTERFACES GRAPHIQUES 179
271 s e l f . _ _ c l i e n t F o r m L i g n e 4 . addWidget ( s e l f . _ _ c o u r r i e l C l i e n t L a b e l )
272 s e l f . _ _ c l i e n t F o r m L i g n e 4 . addWidget ( s e l f . _ _ c o u r r i e l C l i e n t )
273 s e l f . _ _ c h i f f r a g e L a y o u t . addLayout ( s e l f . __clientFormLigne4 )
274 s e l f . _ _ c l i e n t F o r m L i g n e 5 = QtWidgets . QHBoxLayout ( )
275 s e l f . _ _ c l i e n t F o r m L i g n e 5 . addWidget ( s e l f . __nomChantierLabel )
276 s e l f . _ _ c l i e n t F o r m L i g n e 5 . addWidget ( s e l f . __nomChantier )
277 s e l f . _ _ c h i f f r a g e L a y o u t . addLayout ( s e l f . __clientFormLigne5 )
278 s e l f . __boutonsLayout = QtWidgets . QHBoxLayout ( )
279 s e l f . __boutonsLayout . addWidget ( s e l f . _ _ o u v r i r )
280 s e l f . __boutonsLayout . addWidget ( s e l f . _ _ e n r e g i s t r e r )
281 s e l f . __boutonsLayout . addWidget ( s e l f . _ _ e x p o r t e r )
282 s e l f . __boutonsLayout . addWidget ( s e l f . __monter )
283 s e l f . __boutonsLayout . addWidget ( s e l f . _ _ d e s c e n d r e )
284 s e l f . __boutonsLayout . addWidget ( s e l f . _ _ s u p p r i m e r L i g n e )
285 s e l f . _ _ c h i f f r a g e L a y o u t . a d d L a y o u t ( s e l f . __boutonsLayout )
286 s e l f . _ _ c h i f f r a g e L a y o u t . addWidget ( s e l f . _ _ t a b l e C h i f f r a g e )
287 s e l f . _ _ c h i f f r a g e L a y o u t . addWidget ( s e l f . _ _ t o t a u x E s t i m a t i o n L a b e l )
288 s e l f . _ _ p r e s t a t i o n L a y o u t W i d g e t = QtWidgets . QWidget ( )
289 s e l f . __prestationLayoutWidget . setLayout ( s e l f .
__prestationLayout )
290 s e l f . _ _ c h i f f r a g e L a y o u t W i d g e t = QtWidgets . QWidget ( )
291 s e l f . __chiffrageLayoutWidget . setLayout ( s e l f . __chiffrageLayout )
292 s e l f . _ _ c e n t r a l W i d g e t = QtWidgets . Q S p l i t t e r ( )
293 s e l f . _ _ c e n t r a l W i d g e t . addWidget ( s e l f . _ _ p r e s t a t i o n L a y o u t W i d g e t )
294 s e l f . _ _ c e n t r a l W i d g e t . addWidget ( s e l f . _ _ c h i f f r a g e L a y o u t W i d g e t )
295 s e l f . setCentralWidget ( s e l f . __centralWidget )
296 s e l f . peuplerCategories ()
297 s e l f . peuplerPrestations ()
298 s e l f . _ _ l i s t e C a t e g o r i e s . currentIndexChanged . connect ( s e l f .
peuplerPrestations )
299 s e l f . __barreRecherche . textChanged . connect ( s e l f .
peuplerPrestations )
300 s e l f . _ _ l i s t e P r e s t a t i o n s . itemClicked . connect ( s e l f . o u v r i r F i c h e )
301 s e l f . __quantite . valueChanged . connect ( s e l f . c a l c u l e r T o t a u x )
302 s e l f . __tva . v a l u e C h a n g e d . c o n n e c t ( s e l f . c a l c u l e r T o t a u x )
303 s e l f . __ajouterPrestation . c l i c k e d . connect ( s e l f .
ajouterLigneChiffrage )
304 s e l f . __monter . c l i c k e d . c o n n e c t ( s e l f . m o n t e r L i g n e )
305 s e l f . __descendre . c l i c k e d . connect ( s e l f . d e s c e n d r e L i g n e )
306 s e l f . __supprimerLigne . c l i c k e d . connect ( s e l f . supprimerLigne )
307 s e l f . __creerPrestation . c l i c k e d . connect ( s e l f . n o u v e l l e P r e s t a t i o n
)
B.10. LES INTERFACES GRAPHIQUES 181
368 s e l f . _ _ t a b l e C h i f f r a g e . s e t I t e m ( n o L i g n e , 5 , QtWidgets .
QTableWidgetItem ( s t r ( l i g n e P r e s t a t i o n [ " prixTTC " ] ) + "e" ) )
369 t o t a l H T += l i g n e P r e s t a t i o n [ " prixHT " ]
370 totalTVA += l i g n e P r e s t a t i o n [ " prixTVA " ]
371 totalTTC += l i g n e P r e s t a t i o n [ " prixTTC " ]
372 s e l f . _ _ t o t a u x E s t i m a t i o n L a b e l . s e t T e x t ( "HT : " + s t r ( r o u n d (
totalHT , 2 ) ) . r e p l a c e ( " . " , " , " ) + " e\nTVA : " + s t r ( r o u n d (
totalTVA , 2 ) ) . r e p l a c e ( " . " , " , " ) + " e\nTTC : " + s t r ( r o u n d (
totalTTC , 2 ) ) . r e p l a c e ( " . " , " , " ) + " e" )
373 def monterLigne ( s e l f ) :
374 index = s e l f . _ _ t a b l e C h i f f r a g e . currentRow ()
375 i f index > 0:
376 s e l f . _ _ l i g n e s C h i f f r a g e [ i n d e x −1] , s e l f . _ _ l i g n e s C h i f f r a g e [
index ] = s e l f . __lignesChiffrage [ index ] , s e l f .
_ _ l i g n e s C h i f f r a g e [ i n d e x −1]
377 s e l f . a f f i c h e r C h i f f r a g e ()
378 def descendreLigne ( s e l f ) :
379 index = s e l f . _ _ t a b l e C h i f f r a g e . currentRow ()
380 i f i n d e x < l e n ( s e l f . _ _ l i g n e s C h i f f r a g e ) −1:
381 s e l f . _ _ l i g n e s C h i f f r a g e [ i n d e x +1] , s e l f . _ _ l i g n e s C h i f f r a g e [
index ] = s e l f . __lignesChiffrage [ index ] , s e l f .
_ _ l i g n e s C h i f f r a g e [ i n d e x +1]
382 s e l f . a f f i c h e r C h i f f r a g e ()
383 def supprimerLigne ( s e l f ) :
384 index = s e l f . _ _ t a b l e C h i f f r a g e . currentRow ()
385 s e l f . _ _ l i g n e s C h i f f r a g e . pop ( i n d e x )
386 s e l f . a f f i c h e r C h i f f r a g e ()
387 def nouvellePrestation ( s e l f ) :
388 dialog = EditionPrestation ()
389 d i a l o g . exec_ ( )
390 s e l f . peuplerCategories ()
391 s e l f . peuplerPrestations ()
392 s e l f . ouvrirFiche ()
393 def modifierPrestation ( s e l f ) :
394 index = s e l f . _ _ l i s t e P r e s t a t i o n s . currentRow ()
395 idPrestation = s e l f . __prestations [ index ] [ " id " ]
396 d i a l o g = E d i t i o n P r e s t a t i o n ( i d P r e s t a t i o n=i d P r e s t a t i o n )
397 d i a l o g . exec_ ( )
398 s e l f . peuplerCategories ()
399 s e l f . peuplerPrestations ()
400 s e l f . ouvrirFiche ()
401 def supprimerPrestation ( s e l f ) :
402 index = s e l f . _ _ l i s t e P r e s t a t i o n s . currentRow ()
184 ANNEXE B. CORRIGÉS DES EXERCICES