1/106
Algorithmique et Informatique
Cours S’1 2016-2017
Laurent POINTAL (CNRS/LIMSI)
● 6 cours (1h15), DS (1h30)
● 6 TDs (1h30)
● 6 TPs (4h), Partiel (2h, par ½ groupe)
2/106
(Programme Pédagogique National)
PPN
Algorithme
(concevoir et mettre en œuvre)
Traitement numérique de
données expérimentales Tests logiques
Boucles imbriquées Conditionnelles
imbriquées
Tableaux
(1 et 2 dimensions)
Modularité
Gestion entrées/sorties
Test d’un programme Principe
Programmation Orientée Objet
3/106
L’algo… exécuté tous les jours
● Recette de cuisine
● Notice de montage
● Notice de démontage ou de réparation
● Description de trajet
● Étapes
● Séquences
● Répétitions
● Temps
● Modification d’état, de situation
● Outils
● Matériaux / pièces / aliments
4/106
Mousse au chocolat
Temps de préparation : 10 minutes Temps de cuisson : 0 minutes
Ingrédients (pour 4 personnes) :
● 3 œufs
● 100 g chocolat (noir ou au lait)
● 1 sachet de sucre vanillé Préparation de la recette :
● Séparer les blancs des jaunes d'œufs.
● Faire ramollir le chocolat dans une casserole au bain-marie.
● Hors du feu, incorporer les jaunes et le sucre.
● Battre les blancs en neige ferme et les ajouter délicatement au mélange à l'aide d'une spatule.
● Verser dans une terrine ou des verrines et mettre au frais 1 heure ou 2 minimum.
http://www.marmiton.org/recettes/recette_mousse-au-chocolat-facile_13585.aspx
5/106
Recette → Formalisation
● nommer les choses
● savoir ce qu’on peut faire avec
● avec quels outils
● connaître les opérations de base
● procéder aux transformations par étapes
6/106
Formaliser les étapes
Procédure de Séparation des blancs, nécessite : boite d'œufs, nombre d'œufs, bol, saladier
Pour chacun des œufs :
● 1) Prendre un œuf dans la boîte
● 2) Casser l'œuf sur le bord du bol
● Maintenir les 1/2 coquilles au dessus du bol
● 3) Tant que il reste du blanc dans la coquille du bas
● Verser le jaune dans l'autre coquille en faisant tomber le blanc dans le bol
● 4) Si l'œuf est abîmé (odeur / aspect) alors
● Jeter le contenu du bol
● Nettoyer le bol
● Recommencer au 1)
● 4bis) Sinon
● Verser le blanc du bol dans le saladier
7/106
La difficulté
Informatique :
Traitement Automatique de l'Information
● Concret
● Abstrait… virtuel
8/106
Variables
● Nommer les choses
– “l’œuf”, c’est un des 3 œufs qu’on manipule
● Leur donner un sens
– le blanc
– le mélange
Affectation : association d’une valeur à une variable Algo : nom ← valeur littérale ou expression
œuf ← prendre un œuf dans la boite
Python : nom = valeur littérale ou expression
oeuf = prendre_oeuf_dans_boite()
9/106
Types & Opérations
● Savoir ce qu’on peut faire avec les choses
– Casser, séparer (œufs)
– Ramollir (chocolat)
– Battre en neige (blancs d’œufs)
– Incorporer (chocolat mou, dans blancs en neige)
Algo & Python, types de base :
● nombres (Python distingue entier / décimal=flottant)
● logique (booléens Vrai/Faux - Python True / False)
● texte (ou "chaine de caractères")
10/106
Types de bases
Nombres (int, float)
● Opérateurs + - * /
** // %
● Fonctions abs, pow, sin, cos, tan, exp, sqrt…
Logique (bool)
● Opérateurs et (and), ou (or), non (not)
● Comparateurs = (==), ≠ (!=), <, >, ≤ (<=), ≥ (>=)
Expressions
● Regroupement ( )
● Conversions de type, fonctions int, float, str, bool
Texte (str)
● Opérateurs + * in not in
● Fonctions len, .find,
.count, .upper, .split, .join…
11/106
Documentation
● Mémento
● Poly de cours (fr)
● Documentation Python (en)
● Vos tests lors des TPs !
● Aide en ligne : help(…)
12/106
Exemples 1
prenom = "Laurent"
nom = 'Pointal'
salut = "Bonjour, " + prenom + " " + nom presentation = "-" * 40 + '\n' + salut + '\n'
compteur = 4
compteur = compteur + 1 compteur += 1
pi = 3.14159 rayon = 2.5
aire = pi * rayon ** 2
vraioufaux = True or False
13/106
Exemples 2
msg = """Bienvenu,
Ce texte est une présentation pour
le cours "Algorithmique et Informatique"
"""
C = 299792458
mu0 = 1.2566370614e-6
aff = "µ0=" + str(mu0) + "kg⋅m⋅A-2⋅s-2"
est_laurent = 'laurent' in prenom.lower()
14/106
Entrées/Sorties des données
● Saisie clavier / affichage écran (console) ◄
● Interface graphique (GUI)
● Fichiers sur disque ◄
● Données sur le réseau (web…)
● Résultats de calculs
● Instruments de mesure
● Bases de données
15/106
Saisie / Affichage
● Affichage écran : fonction print(…) print("π="+str(pi)+"rad")
print("Aire:", aire, "m²")
● Saisie clavier : fonction input("msg") input("Pause…")
nom = input("Saisissez votre nom:") age = int(input("Et votre age:"))
Conversions !
16/106
Logique Booléenne
● non (not) ● et (and)
Important :
conditions logiques
● si (if)
● tant que (while)
● ou (or)
17/106
Si (if), Sinon (else)
4) Si l'œuf est abîmé (odeur / aspect) alors
– Jeter le contenu du bol
– Nettoyer le bol
– Recommencer au 1)
4bis) Sinon
– Verser le blanc du bol dans le saladier
if oeuf_abime()==True:
jeter_contenu_bol() nettoyer_bol()
recommencer() else:
verser_bol_dans_saladier()
Bloc d'instructions Instruction Composée
L'indentation (décalage) délimite le bloc d'instructions
Le : introduit le bloc d'instructions
18/106
Si imbriqués
if moyUE1>=8 and moyUE2>=8:
if moyGen>=10:
print("Semestre validé!") else:
if (moyGen+moySemPrec)/2>=10:
print("Compensation semestre précédent") print("Semestre validé!")
else:
print("Compensation impossible) print("Semestre non validé")
else:
print("Semestre non validé")
19/106
Sinon Si (elif)
if v>=90 and v<100:
prefix = "nona"
elif v>=80:
prefix = "octa"
elif v>=70:
prefix = "septua"
elif v>=60:
prefix = "sexa"
elif v>=50:
prefix = "quinqua"
elif v>=40:
prefix = "quadra"
else:
prefix = ""
● Enchaînement de tests
● Bloc du premier test vérifié exécuté
● Tests et blocs
suivants ignorés
⇒ un seul bloc, au plus, est exécuté !
20/106
Conteneurs, Séquences
Éléments
dénombrables
● Boite à œufs
● Tiroir bacs à vis
● Armoire documents
● Sac à bonbons
● Vrac / ordonnés
● Accès séquentiel / direct
● Accès index
(numéros d’ordres consécutifs) / clé
● Valeurs uniques / répétables
21/106
Séquence de caractères : str
Opérateurs et fonctions
>>> s = "Hello you"
>>> len(s) 9
>>> 'you' in s True
>>> 'I' not in s True
>>> min(s) ' '
>>> max(s) 'y'
>>> sorted(s)
[' ', 'H', 'e', 'l', 'l', 'o', 'o', 'u', 'y']
>>> s.count('o') 2
>>> s.index('y') 6
>>> "machin" + " chose"
'machin chose'
Accès aux éléments: indexation
>>> s[0]
'H'
>>> s[1]
'e'
>>> s[-1]
'u'
>>> s[-2]
'o'
>>> s[2:5]
'llo'
>>> s[:5]
'Hello'
>>> s[-3:]
'you'
>>> s[:]
'Hello you'
>>> s[::2]
'Hloyu'
>>> s[::-1]
'uoy olleH'
22/106
Séquences de … : list (& tuple )
Opérateurs et fonctions
>>> l = [3,7,9,1,2,8,7,4]
>>> len(l) 8
>>> 2 in l True
>>> 5 not in l True
>>> min(l) 1
>>> max(l) 9
>>> sorted(l)
[1, 2, 3, 4, 7, 7, 8, 9]
>>> sum(l) 41
>>> l.count(7) 2
>>> l.index(4) 7
>>> [1,2,3] + [4,5,6]
[1, 2, 3, 4, 5, 6]
Accès aux éléments : indexation
>>> l[0]
3
>>> l[1]
7
>>> l[-1]
4
>>> l[-2]
7
>>> l[2:5]
[9, 1, 2]
>>> l[:5]
[3, 7, 9, 1, 2]
>>> l[-3:]
[8, 7, 4]
>>> l[:]
[3, 7, 9, 1, 2, 8, 7, 4]
>>> l[::2]
[3, 9, 2, 7]
>>> l[::-1]
[4, 7, 8, 2, 1, 9, 7, 3]
23/106
Modification de list
Fonctions
>>> l.insert(2, 12); l
[3, 7, 12, 9, 1, 2, 8, 7, 4]
>>> l.remove(8); l
[3, 7, 12, 9, 1, 2, 7, 4]
>>> l.pop(4) 1
>>> l
[3, 7, 12, 9, 2, 7, 4]
>>> l.reverse(); l
[4, 7, 2, 9, 12, 7, 3]
>>> l.sort(); l
[2, 3, 4, 7, 7, 9, 12]
>>> l.append(5); l
[2, 3, 4, 7, 7, 9, 12, 5]
>>> l.extend([6,1]); l
[2, 3, 4, 7, 7, 9, 12, 5, 6, 1]
Modification des éléments
>>> del l[5]; l
[2, 3, 4, 7, 7, 12, 5, 6, 1]
>>> del l[2:8]; l [2, 3, 1]
>>> l[-1] = 15; l [2, 3, 15]
>>> l[1:3] = [8,1,9,3]; l [2, 8, 1, 9, 3]
>>> l[2:2] = [15,17]; l [2, 8, 15, 17, 1, 9, 3]
>>> l.clear()
>>> l []
24/106
Imbrications de list
>>> len(l) 4
>>> l[1]
[5, 25]
>>> len(l[1]) 2
>>> l[-1]
[8, 64]
>>> l[1][0]
5
>>> l[1][1]
25
>>> x,y = l[2]
>>> x 7
>>> y 49
>>> l[1][0] = 6
>>> l[2] = [4,16]
>>> l=[[2,4],[5,25],[7,49],[8,64]]
« Tableau à 2 dimensions »
Premier index Second index
25/106
Mutable / Immutable
Tuple (immutable)
>>> t1 = (1,2,3)
>>> t2 = t1
>>> t2
(1, 2, 3)
>>> t2 is t1 True
>>> t2[1] = 5 Traceback (…):
File "<…>",line 1,in <…>
TypeError: 'tuple' object does not support item
assignment
Liste (mutable)
>>> l1 = [1,2,3]
>>> l2 = l1
>>> l2 [1,2,3]
>>> l2 is l1 True
>>> l2[1] = 5
>>> l2
[1, 5, 3]
>>> l1
[1, 5, 3]
26/106
Itération sur les Valeurs : for
● Conteneur (séquence ordonnée ou non…)
● Faire un traitement sur chaque valeur, une par une
Algo :
pour chaque élève dans promo:
afficher(élève.nom) Python :
for x in [1,4,8,10]:
print(x, x**2)
27/106
Séquence d'entiers : range
● Séquence immutable d'entiers générés à la demande
>>> range(10) range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(5,10)) [5, 6, 7, 8, 9]
>>> list(range(2,10,2)) [2, 4, 6, 8]
>>> list(range(10,0,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> list(range(10,8)) []
>>> range(0,100000000000,100)[9424]
942400
28/106
Itération sur les Index: for
● Conteneur (séquence ordonnée…) lst = [1,4,8,10]
for i in range(len(lst)):
v = lst[i]
lst[i] = v ** 2
● Itération sur index ET valeur
for i,v in enumerate(lst):
lst[i] = v ** 2
29/106
Boucles imbriquées
● Affichage ax+b pour une série de x et une série de a et b
for a,b in [[1,3],[1,4],[2,7]]:
for x in range(10):
print(a,b,x/10,a*(x/10)+b)
a b x
1 3 0.0 3.0 1 3 0.1 3.1
…
1 3 0.8 3.8 1 3 0.9 3.9 1 4 0.0 4.0
…
1 4 0.8 4.8 1 4 0.9 4.9 2 7 0.0 7.0 2 7 0.1 7.2 2 7 0.2 7.4
…2 7 0.9 8.8
30/106
Boucle conditionnelle
Tant que il reste du blanc dans la coquille du bas
• Verser le jaune dans l'autre coquille en faisant tomber le blanc dans le bol
Battre les blancs jusqu'à ce qu'ils tiennent quand on retourne le saladier
Si l'œuf est abîmé (odeur / aspect) alors
• …
• Recommencer
31/106
Itération sur condition : while
● Condition de boucle
● Faire un traitement répété à chaque itération Algo : boire jusqu'à la dernière goutte
contenu ← 330 # poids en grammes pour 33 cl tant que contenu > 0,01: # ~poids 1 goutte contenu ← contenu / 2 # boire la moitié Python : trouver le premier n tel que Σ 1 à n (compris) > 100 n = 0
som = 0
while som <= 100:
n = n + 1
som = som + n # On a bien som pour le n
32/106
Boucle Ignorée
● La condition est fausse dès avant la boucle Exemple : chauffage d'un four
consigne ← 25 # °C
fixe_four(consigne) # syst. externe t ← lecture_température # sur sonde tant que t < consigne:
attendre 10 secondes
t ← lecture_température
33/106
Boucle sans fin
● La condition reste toujours vraie
Exemple : bug dans la vérification de saisie
v = int(input("Entier entre 10 et"
" 20 :")) while v<20 or v>10:
print("Valeur invalide !")
v = int(input("Entier entre"
" 10 et 20 :"))
34/106
while vs if
while condition:
⇒ répétition
Le bloc d'instructions sera exécuté 0 à ∞ fois.
if condition:
⇒ alternative
Le bloc d'instructions sera exécuté au plus 1 fois.
Si on enchaîne des elif… elif… else, un seul des blocs sera exécuté, une seule fois
35/106
while vs for
while condition:
⇒ répétition
Le bloc d'instructions sera exécuté 0 à ∞ fois.
for v in seq:
⇒ parcours séquence
Le bloc d'instructions sera exécuté au
maximum autant de fois qu'il y a de valeurs dans
la séquence.
36/106
Itération suivante prématurée : continue
continue fait passer immédiatement à
l'itération suivante pour la boucle while ou for la plus proche.
Utilisation typique : Filtrage des cas inintéressants sans accumuler les imbrications if.
À partir de n°INSEE,
comptage des hommes regroupés par mois de naissance :
cpt=[0] * 12
for n in liste_n:
s=str(n)
if s[0]!='1':
continue
m=int(s[3:5])-1 cpt[m]=cpt[m]+1
37/106
Sortie prématurée de boucle : break
break fait sortir
immédiatement de la boucle while ou for la plus proche.
Utilisation typique :
● Recherche d'une valeur, arrêt de boucle quand trouvée.
● Déport de la condition de boucle dans le corps.
Recherche numérique de l'abscisse où une fonction f(x)→-x²+7x+3 deviens
décroissante sur [0,100] : x = 0.0
y1 = f(x)
while x<100:
x = x + 0.01 y2 = f(x)
if y2 < y1:
break y1 = y2
print("trouve x=",x)
38/106
Sortie normale de boucle : else
sortie de la boucle while ou for de même niveau.
« normale » = sans passer par un break
Recherche d'une valeur dans une séquence :
for v in seq:
if good(v):
res = v break
else:
# Pas trouvé res = None
! Construction spécifique Python !
39/106
Le jusqu'à en while
● Besoin d'exécuter au moins une fois le corps de boucle pour pouvoir évaluer l'expression de
condition
Exemple : faire saisir un nombre entier n à l'utilisateur jusqu'à ce que le nombre saisi soit positif et pair
n_ok = False
while not n_ok:
s = input("Entier positif pair:") n = int(s)
n_ok = (n>=0 and n%2==0)
40/106
Le recommencer en while
● Définir la condition qui fait recommencer.
● La placer comme condition d'une boucle while.
● Initialiser les variables pour pouvoir entrer dans la boucle.
Exemple : recommencer le lancer de couteau
reussi = False
while not reussi:
lancer_couteau()
reussi = couteau_dans_cible()
lancer couteau
dans cible ? recommencer
oui non
41/106
Portée de boucle
● Difficulté de break et continue avec les boucles imbriquées.
● Variables de contrôle en plus.
● Tests sur ces variables.
Recherche numérique de x et a où une fonction f(x,a)→-ax²+7x+3 deviens décroissante :
trouve = False
for a in range(-10,10):
x = 0.0
y1 = f(x, a) while x<100:
x = x + 0.01 y2 = f(x, a) if y2 < y1:
print("trouve x=",x, "pour a=",a) trouve = True
break # sortie du while y1 = y2
if trouve:
break # sortie du for
42/106
Séparation des blancs…
Procédure de Séparation des blancs, nécessite : boite d'œufs, nombre
d'œufs, bol, saladier
Pour chacun des œufs :
– 1) Prendre un œuf dans la boîte
– 2) Casser l'œuf sur le bord du bol
● Maintenir les 1/2 coquilles au dessus du bol
– 3) Tant que il reste du blanc dans la coquille du bas
● Verser le jaune dans l'autre coquille en faisant tomber le blanc dans le bol
– 4) Si l'œuf est abîmé (odeur / aspect) alors
● Jeter le contenu du bol
● Nettoyer le bol
● Recommencer au 1)
– 4bis) Sinon
● Verser le blanc du bol dans le saladier
def sepblancs(bte,n,bol,sal):
for i in range(n):
while estvide(bol):
o = bte.pop() casser(o,bol)
while reste_blanc(o):
transvaser(o,bol) if mauvais(bol):
vider_nettoyer(bol) else :
verser(bol,sal) return sal
43/106
Les fonctions
●
Décomposer les problèmes
●
Réutiliser ce qui
marche
44/106
Définition d'une fonction
def sepblancs(bte,n,bol,sal):
return sal
Corps de la fonction (bloc d'instructions)
Nom (identificateur) Paramètres
Retour du résultat
(production de la fonction)
45/106
Exécution d'une fonction
Utilisation du résultat
(ici stockage) Fourniture des arguments (pour les paramètres)
46/106
Écrire vs Faire
Définition
On explique comment faire
● Mot clé def
● Vérification de la syntaxe
● Stockage de la fonction
– liste des paramètres
– instructions du corps
– associés au nom
définition 1 fois
Exécution (appel)
On fabrique
● Appel avec nom()
● Fourniture
d'arguments pour les paramètres
● Récupération du résultat
appels autant que besoin
47/106
Définir vs Exécuter
def mmm(lst):
"Calcul min,max,moyenne"
mi = lst[0]
ma = lst[0]
som = lst[0]
for v in lst[1:]:
if v<mi:
mi=v if v>ma:
ma=v
som = som + v mo = som / len(lst) return (mi,ma,mo)
l1=[1,3.2,5.9,4,2.8]
print("Stats :",mmm(l1))
#Stats : (1, 5.9, 3.3800000000000003)
for i in range(10,16):
l2=[x/10 for x in
range(i, i+10)]
print("Stats",i,":",mmm(l2))
#Stats 10 : (1.0, 1.9, 1.45)
#Stats 11 : (1.1, 2.0, 1.55)
#Stats 12 : (1.2, 2.1, 1.65)
#Stats 13 : (1.3, 2.2, 1.75)
#Stats 14 : (1.4, 2.3, 1.85)
#Stats 15 : (1.5, 2.4, 1.95)
48/106
Sortie de la fonction
● Absence d'instruction return
Sortie à la fin du bloc corps de la fonction
● Instruction return
Sortie immédiate lors de l'exécution du return (instructions suivantes non exécutées !)
49/106
Résultat de la fonction
● Pas de return, ou return sans valeur Retour de la valeur None
On parle aussi de procédure.
En TP écrire explicitement : return None
● Instruction return spécifiant une valeur
Retour de la valeur spécifiée : return res Si plusieurs valeurs → tuple : return a,b,c
50/106
Utilisation du résultat
● Stockage dans une (des) variable(s)
long = sqrt(x**2 + y**2) q,r = divmod(13,4)
● Utilisation directe dans une expression print("√x=", sqrt(x))
if cotadj != hypot * cos(angle):
● Si pas d'utilisation… valeur perdue
51/106
Valeur par défaut
● Évite de fournir un argument (utilisation du défaut) int("18") → 18
int("18", base=16) → 24
● Définition de la fonction
def int(x, base=10):
● Attention aux défauts mutables…
→Utiliser None, et tester dans la fonction.
52/106
Défaut mutable… effet mémoire
>>> def f(x, l=[]):
l.append(x) print(l)
>>> f(3) [3]
>>> f(2) [3, 2]
>>> f(12) [3, 2, 12]
>>> f(2)
[3, 2, 12, 2]
>>> def f(x,l=None):
if l is None:
l = []
l.append(x) print(l)
>>> f(3) [3]
>>> f(2) [2]
>>> f(12) [12]
>>> f(2) [2]
53/106
Nombre variable d'arguments
● Permet d'avoir une fonction souple
print("x=",x,"et y=",y, "en cm²")
● Définition de la fonction def print(*args) :
# args reçu sous forme de tuple for v in args:
stdout.write(str(v))
54/106
Portée des variables
● Globales
– définies au niveau du module / fichier par affectation
– définies par affectation
dans une fonction avec la directive :
global nomvar
● Locales
– définies dans les
fonctions par affectation
– + paramètres, dans les fonctions
● Globales visibles de partout dans le
module, y-compris des fonctions
● Locales et paramètres inaccessibles à
l'extérieur de leur fonction de définition
55/106
Globales / effet de bord
curmax = 0 lst1 = []
lst2 = []
def ajouter(n, l):
global curmax lst1.append(n) l.append(n)
if n>curmax:
curmax = n return None
ajouter(2, lst2) ajouter(4, lst2) ajouter(12, lst2) ajouter(7, lst2) print(curmax)
print(lst1) print(lst2)
Affichage:
12
[2, 4, 12, 7]
[2, 4, 12, 7]
● lst1 → liste globale visible et modifié
● curmax → valeur entière réaffectée dans la fonction, directive global
● lst2 → liste modifiée par effet de bord (paramètre l mutable)
56/106
Corps de la fonction
La boîte noire
paramètres
valeurs de retour
Pour limiter les problèmes, essayer :
Tout ce qui rentre : par les paramètres
Tout ce qui sort :
par les valeurs de retour
● Pas de modification directe de globale
● Pas de modification de paramètre mutable
● Accès aux globales constantes
57/106
Modules : Organiser le code
●
Décomposer les problèmes
●
Réutiliser ce qui marche
Paquet, Package, Librairie, Library, Module…
58/106
Module ↔ Fichier Python
● Import par
import nommod
(sans le .py!)
● Liste de répertoires où sont cherchés les
fichiers modules
– PYTHONPATH
– import sys
print(sys.path)
#!/usr/bin/python3
#-*- coding : utf-8 -*-
"""Docs"""
import math MAXI=3
cpt=0
def f(x):
"""Doc"""
return 3*x*math.sin(x) v=int(input("x? "))
print(f(v))
59/106
Import Module / Noms
● Accès par le module
import math
x = math.sin(3*math.pi)
● Accès direct au nom
from math import sin,pi x = sin(3*pi)
from math import (sin,pi, cos,tan,sqrt)
Important :
accès aux variables globales d'un module
► passer par le module (sauf pour les constantes)
60/106
Renommage à l 'import
● Mot clé as lors de l'import
● Renommage d'un nom importé (module / fonction / variable…) - un genre d'alias
from math import sqrt as racine_carree import matplotlib.pyplot as plt
from math import pi as π
from numpy import (array as tableau, around as arrondi)
61/106
Réutiliser…
Fournir une page sur le Web
import time
from http.server import HTTPServer, BaseHTTPRequestHandler PORT = 8080
page = """<html><head><meta charset="UTF-8">
<title>Mon Ptit Web</title></head><body>
<p>Bonjour, il est {temps}.<br/>Page demandée: {chemin}.</p>
</body></html>
"""
class Traitement(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html') self.end_headers()
s = page.format(temps=time.strftime('%Y-%m-%d %H:%M:%S'), chemin=self.path)
self.wfile.write(s.encode('utf-8')) server = HTTPServer(('', PORT), Traitement) server.serve_forever()
62/106
Gestion des Erreurs
(parallèle appel de fonction = niveau hiérarchique)
Fonction Big Boss
↳Fonction Chef de département
↳Fonction Gestionnaire de Service
↳Fonction Responsable de production ↳Fonction Technicien atelier
↳Fonction Stagiaire
Qui détecte l'erreur
Comment est-elle remontée
Qui décide que faire (corriger / arrêter)
63/106
Tests de Codes d'erreurs
● Transmission du code
– Variable globale
– Retour de valeur des fonctions
● Signalisation de l'erreur
– Retour de valeurs spécifiques
– Indicateur en plus de la valeur de retour
● Traitement de l'erreur
– À chaque niveau d'appel, pour chaque fonction, un cas particulier (ou risque de laisser passer une erreur
signalée)
64/106
Exemple (langage C)
#include <stdio.h>
#include <errno.h>
int lecture_data(const char* nomfic) { FILE* f = NULL;
errno = 0;
f = open(nomfic, "rt");
if (f == NULL) {
fprintf(stderr,
"Erreur ouverture '%s': %s.\n", nomfic, strerror(errno));
return -1; // drapeau problème }
// après, la suite...
}
65/106
Mécanisme d'Exceptions
Séparer :
● Bloc try: d'instructions en situation normale (la plus courante)
● Blocs except: d'instructions pour traiter les erreurs
def saisie_calcul() : try:
x=int(input("x?")) res = 3*x+2
return res
except ValueError:
print("Valeur invalide à la saisie") return 0
66/106
Lever une exception
● Lors de la détection d'un cas d'erreur : raise …
if x<0 :
raise ValueError("x < 0 interdit")
67/106
Intercepter une exception
● Tout intercepter (à éviter):
except:
● Intercepter juste le nécessaire (attendu) — mieux
except Exception: # très (trop) générique except ValueError: # plus spécifique
except OSError as e:
except (FileNotFoundError,TimeoutError) as e :
● Si besoin, on peut avoir plusieurs blocs except, traitant différents types d'erreurs.
68/106
Traiter une exception
Dans le bloc d'instruction du except:
● Corriger ce qui peut l'être
● Si possible, en conserver une trace (print, log, fichier, message utilisateur…)
● Au final :
– Continuer à la suite (et si dans une boucle, peut-être recommencer) - rien à indiquer
– Propager l'exception au dessus, indiquer :
raise # tout seul
● Éviter d'intercepter et masquer silencieusement une exception.
69/106
Extension du Mécanisme
(python)En plus de:
● Bloc try … : en situation normale
● Blocs except … : pour traiter les erreurs On ajoute :
● Bloc finally: exécuté dans tous les cas
– libération de ressources (ex. fermeture de fichier)
● Bloc else: exécuté si try … : s'est bien passé
70/106
Stocker des données : Fichiers
● Résister aux coupures de courant ! ☺
● Ranger les données
● Partager, transmettre les données
● Conserver les données, les archiver
● Faire évoluer les données, disposer de différentes versions
71/106
Système de stockage structuré
Données accessibles par blocs d'octets
Partition Partition
Support
“disque”
Partition
Organisation des blocs
Système de Fichiers (File-System)
8
1
6
5 3
4
7 2
Fichiers
1 2 3 4 5 6 7 8
Séquence ordonnée d'octets
Nommage des fichiers, gestion des blocs, des
droits d'accès…
Abstraction de l'accès aux fichiers Système
d'exploitation
Fichiers locaux/distants,
“montage” des partitions, caches lecture/écriture.
9
9
RAID, NAS, SAN…
Blocs Volumes
72/106
Système de stockage organisé
Mes documents\
C:\
Users\
joe\
photo.jpg Images\
Wallpapers\
Vidéos\
Ziq\
Téléchargement\
Bureau\
Exemple sous Windows: Exemple sous Unix:
Documents/
/
home/
joe/
photo.jpg Images/
Wallpapers/
Vidéos/
Ziq/
Téléchargement/
Bureau/
Note : pour simplifier à l'usage… éviter les espaces (remplacer par _) et les caractères accentués.
commande tree
Arborescence de répertoires (directory) et de fichiers.
73/106
Chemin absolu / relatif
.. répertoire parent
Identification du fichier sur disque: chemin = répertoire + nom
C:\Users\joe\Mes documents\Images\photo.jpg /home/joe/Documents/Images/photo.jpg
Chemin d'accès absolu:
Spécification de la « racine »
Chemin d'accès relatif au « répertoire courant »
>>> import os
>>> os.getcwd() '/home/joe'
>>> os.chdir('Document')
>>> os.getcwd()
'/home/joe/Documents'
>>> os.chdir('Ziq')
>>> os.getcwd()
'/home/joe/Documents/Ziq'
>>> import os
>>> os.getcwd() ''C:\\Users\\joe'
>>> os.chdir('Mes documents')
>>> os.getcwd()
''C:\\Users\\joe\\Mes documents'
>>> os.chdir('Ziq')
>>> os.getcwd()
''C:\\Users\\joe\\Mes documents\\Ziq' photo.jpg
../photo.jpg
Images/photo.jpg ../Images/photo.jpg
74/106
Piège chemins sous Windows
\ est le caractère d'échappement des chaînes
(\n retour à la ligne, \t tabulation, etc)
On ne peut pas l'utiliser pour un chemin sans précautions…
● Doubler les \ dans des chaînes normales
"C:\\Users"
● Désactiver l'interprétation des \ dans des chaînes « raw string » (brutes), préfixées par r
r"C:\Users"
● Utiliser des / à la place des \, comme sous Unix
"C:/Users"
● Utiliser la fonction os.path.join(), qui se charge de placer le bon séparateur from os.path import join
join("C :","Users")
Note : le \ ne peut pas être placé en fin de chaîne sans être doublé, cela produit une erreur de syntaxe.
75/106
Fichiers « structurés »
● Utiliser les librairies / modules dédiés
– éviter d'avoir à écrire le code pour manipuler le contenu du fichier
– nombreuses normes… souvent pas complètement respectées
● Vidéos / Images / Sons (.mp4, .ogm, .jpg, .png, .svg, .tiff, .wav, .mp3, .flac…)
● Données scientifiques (.hdf5, .cdf, .nc, .kgml, .cif, .dem…)
● Données textuelles structurées (.xml, .html, .svg, .json, .csv…)
● Et tout le reste (.pdf, .xlsx .docx, .odt…)
76/106
Accéder au fichier : ouverture
Demande d'accès via le système d’exploitation
Fonction standard open() → Objet fichier pour les accès
f = open("nomFichier","modeAccès",encoding="utf8")
Compréhension des accents des fichiers textes.
● "r" read (lecture, par défaut)
● "w" write (écriture, création fichier neuf vide)
● "a" append (ajout à la fin) Et en plus
● "t" texte (par défaut)
● "b" binaire (sans interprétation des fin de ligne)
● "+" modification (lecture+écriture) Chemin d'accès au fichier
77/106
Les problèmes d'encodage
Contenu du fichier = séquence ordonnée d’octets
55 89 e5 45 f4 04 00 c9 8b c7 45 f8 05 aa c0 8f 8b 45 f8 8b …
Fichier texte, il faut donner la signification des octets…
● Nombre d'octets pour un caractère… nombre de caractères possibles
● Fin de ligne (CR, CR+LF, LF)
● Table de correspondance code (octets) / caractère
➢ Très nombreuses normes de correspondance code ↔caractère
(ascii, latin1 / iso-8859-1, ansi, ebcdic, cp1252, mac_roman, big5, euc_jp, unicode…)
➢ + Façon de stocker les codes (nombre d'octets fixes/variables, ordre des octets)
(U32, U16, UTF8, UTF16BE, UTF16LE…)
En Python, str = chaînes Unicode, on préférera utf8
78/106
Lire un fichier texte
f = open("toto.txt", 'r', encoding='utf-8')
Lecture de :
● Caractère(s)
s = f.read(1) # lecture 1 caractère s = f.read(5) # lecture 5 caractères
● Ligne(s)
s = f.readline() # lecture 1 ligne
s = f.readline(20) # lecture 1 ligne, au max 20 car l = f.readlines() # lecture toute les lignes
l = f.readlines(3) # lecture 3 lignes
● Totalité
s = f.read() # l'intégralité en une chaîne Chaque lecture avance le « curseur de lecture » dans le fichier.
79/106
Écrire dans un fichier texte
f = open("toto.txt", 'w', encoding='utf-8')
● Caractère(s) — on écrit toujours une chaîne à la fois f.write('X') # Un caractère
f.write("Le texte") # Plusieurs caractères f.write(s) # Une chaîne
print("x =",x,file=f) # En utilisant print()
● Ligne(s)
f.writelines(["Une\n", "Deux\n", "Trois\n"]) f.writelines(l) # Une liste de chaînes Penser à mettre explicitement les retours à la ligne (sauf avec print()).
80/106
Ouvrir… fermer
Lorsqu'on a terminé les opérations sur le fichier, il faut obligatoirement faire :
f.close()
● Libère les ressources allouées (par Python, par le système d'exploitation)
● Assure l'écriture sur le disque du contenu des
« caches » encore en mémoire.
81/106
Tout ensemble
f = open("discours.txt", "r", encoding="utf-8") try:
cpt = 0
s = f.readline() while s != '':
if 'IUT' in s:
cpt = cpt + 1 s = f.readline()
print("Lu", cpt, "lignes avec IUT") finally:
f.close()
82/106
Boucle for sur fichier
f = open("discours.txt", "r", encoding="utf-8") try:
cpt = 0
for s in f :
if 'IUT' in s:
cpt = cpt + 1
print("Lu", cpt, "lignes avec IUT") finally:
f.close()
83/106
Fermeture implicite… with
Utilisation d'un bloc gardé with
cpt = 0
with open("discours.txt","r",encoding="utf-8") as f:
for s in f :
if 'IUT' in s:
cpt = cpt + 1
print("Lu", cpt, "lignes avec IUT")
84/106
Lecture/écriture de nombres
Écriture lstx=[1,4,8,11,15]
lsty=[0.2,1.2,-3.2,0.6,5.4]
f = open("data.txt",'w') for i in range(len(lstx)):
x = lstx[i]
y = lsty[i]
s = str(x)+' '+str(y)+'\n' f.write(s)
f.close()
Lecture
lstx=[]
lsty=[]
f = open("data.txt",'w') for ligne in f:
items = ligne.split()
lstx.append(int(items[0])) lsty.append(float(items[1])) f.close()
85/106
Extras sur les fichiers
● Gestion du « curseur de lecture/écriture »
# Mémorisation position actuelle p = f.tell()
# Retour au début (index 0) f.seek(0)
# Retour à une position p f.seek(p)
# Déplacement à la fin f.seek(0,os.SEEK_END)
● Vidage des cache d'écriture sur disque (sans avoir à fermer/rouvrir) f.flush()
● Troncature du fichier à une taille donnée f.truncate(size)
86/106
Manipulations système de fichiers
Copie, déplacements, informations sur les fichiers,
changements d'attributs, droits d'accès, manipulation de chemins, liste de fichiers, répertoire courant…
● Module os (information, copie, suppression, listing, répertoire courant…)
● Module os.path (manipulation noms, extensions et chemins)
● Module shutil (copie/déplacement fichiers /
arborescences), filecmp (comparaisons fichiers / répertoires)
● Module glob (listing fichiers sur motif (ex. *.txt)) et fnmatch (identification sur motif)
87/106
D’autres Conteneurs…
Déjà vu :
● Liste (lst)
● Tuple (tuple)
● Chaîne de caractères (str)
➔ Données ordonnées
➔ Données répétables
➔ Accès direct par index (position)
➔ Index entiers 0…n-1 (pas de « trou »)
➔ Recherche séquentielle (présence/absence, index)
➔ Insertion/suppression (liste) nécessitent des décalages
88/106
Les ensembles
➔ Ordre indéfini (et variable) — pas d’index
➔ Données uniques (un seul exemplaire)
➔ Test direct de présence (ou d’absence)
➔ Insertion/suppression peu coûteux
Test à partir de 100000 entiers (0-99999 dans le désordre)
● Recherche d’une valeur présente (au milieu dans la liste) (10000×)
– Liste : 11 sec
– Set : 1,6 msec
● Recherche d’une valeur absente (10000×)
– Liste : 12 sec
– Set : 0,3 msec
● Ajout de 1000 nouveaux éléments (au milieu dans la liste)
– Liste : 20 msec
– Set : 75µsec
89/106
Ensembles : set
Opérateurs et fonctions
>>> e = {3,7,9,1,2,8,7,4}
>>> len(e) 7
>>> 2 in e True
>>> 5 not in e True
>>> max(e) 9
>>> min(e) 1
>>> sorted(e)
[1, 2, 3, 4, 7, 8, 9]
>>> sum(e) 34
>>> x = set("Hello you")
>>> x
{'e', 'o', 'H', 'y', 'u', ' ', 'l'}
Modification
>>> e.add(100000)
>>> e.remove(8)
>>> e
{100000, 1, 2, 3, 4, 7, 9}
Boucles
>>> for v in e:
... print(v) 1
2 3 4 7 8 9
90/106
Opérations ensemblistes
>>> s1 = set("abcde")
>>> s2 = set("defg")
>>> s1 - s2
{'a', 'c', 'b'}
>>> s1 & s2 {'e', 'd'}
>>> s1 | s2
{'e', 'd', 'c', 'g', 'b', 'a', 'f'}
>>> s1 ^ s2
{'c', 'g', 'b', 'a', 'f'}
>>> {'c','b'} <= s1 True
>>> s3 = s1.copy()
>>> s3.update(s2)
>>> s3
{'e', 'd', 'c', 'g', 'b', 'a', 'f'}
>>> s3.pop() 'e'
>>> s3.pop() 'd'
>>> s3
{'c', 'g', 'b', 'a', 'f'}
>>> s3.clear()
>>> bigset=set(range(100000000))
91/106
Les dictionnaires
➔ Associations clé → valeur
➔ Accès direct à la valeur via la clé (index=clé)
➔ Ordre indéfini (et variable)
➔ Clés uniques, test direct de présence de clé
➔ Insertion/suppression peu coûteux
● Dictionnaire = tableau associatif = hash map…
● Même base que les ensembles… avec une relation clé/valeur
● Utilisé partout en interne dans Python (variable = clé dans un dictionnaire «espace de noms»)