Fichier CSV et SGBD
Voici 2 activités assez différentes, mais complémentaires :
- Une sur la manipulation de données sur des fichiers CSV (ce qui permet de réviser au passage le traitement
de données en table). On met en évidence les difficultés à s'assurer
- d'une part la bonne validité d'une condition simple : ne pas avoir 2 pseudos identiques dans une table,
- d'autre part la bonne manipulation des données par diverses instances du programme d'inscription.
- La deuxième permet d'appréhender un SGBD avec l'utilisation du logiciel DB Browser.
Manipulations de données sur des fichiers CSV
Révisions sur le traitement en table avec Python
Le format CSV
Le format CSV (Comma Separated Values, données avec des séparateurs) est un format de fichier universel et le plus simple à manipuler, notamment en Python.
C'est aussi un format très flexible : on peut troquer la virgule contre un point virgule ou une tabulation comme séparateur de données, si celles-ci contiennent elles-mêmes des virgules (par exemple en français où la virgule peut être utilisée pour écrire des nombres décimaux).
Nom;Prénom;Âge;Pseudo
Garcia;Serge;40;sergent_garcia
De la Vega;Diego;17;ZoRRo
McDuck;Scrooge;108;Picsou
Il faut imaginer le contenu de ce fichier comme un tableau, dont les lignes sont les lignes du fichier, et
les séparations entre les colonnes sont indiquées par les caractères ;.
La première ligne contient des éléments particuliers appelés descripteurs, qui indiquent quelle donnée contient la colonne correspondante.
Ici, il s'agit de Nom, Prénom, Âge et Pseudo.
Chacune des lignes suivantes contient un enregistrement, qui associe une valeur à chaque descripteur. Les valeurs sont données dans le même ordre que le sont les descripteurs dans la première ligne.
Ici, par exemple, la dernière ligne contient l'enregistrement :
Ouverture d'une table CSV en Python
Il existe 2 façons pour ouvrir un fichier en Python :
fichier_source = open('matable.csv','r',encoding='utf-8')
et
with open('matable.csv','r',encoding='utf-8') as fichier_source:
Ces 2 façons ouvrent toutes les deux un fichier matable.csv en lecture seule ('r') avec un encodage
en UTF-8.
La ligne de code fichier_source = open('matable.csv','r',encoding='utf-8') affecte à fichier_source un
objet python fournissant une interface _io.TextIOWrapper permettant d'effectuer diverses opérations sur le
fichier ouvert, dont obtenir son contenu.
La ligne with open('matable.csv','r',encoding='utf-8') as fichier_source: effectue la même affectation, mais
limite la validité de l'objet fichier_source au bloc indenté immédiatement en dessous. Au-delà de ce bloc,
le fichier n'est plus ouvert et y accéder via fichier_source provoque une erreur d'exécution.
Lorsque l'on n'utilise pas de bloc with, il convient de fermer le fichier avec la méthode close() de l'objet
fichier_source. Si on omet cette opération, python se charge de fermer lui-même le fichier, mais seulement lorsqu'il
est certain que l'objet fichier_source n'est plus utilisé, ce qui peut être à la fin du programme.
Ces 2 codes sont donc équivalents :
# Premier code
fichier_source = open('matable.csv','r',encoding='utf-8')
# des traitements...
fichier_source.close()
# Second code
with open('matable.csv','r',encoding='utf-8') as fichier_source:
pass # des traitements...
Lecture d'une table CSV en python
On pourra utiliser la méthode Python readlines()
with open('matable.csv','r',encoding='utf-8') as fichier_source:
mon_objet = fichier_source.readlines()
La méthode readlines() de l'objet fichier_source affecte à mon_objet un tableau de chaînes de caractères
correspondant, dans l'ordre de lecture, aux différentes lignes du fichier texte ouvert dans mon_objet.
Après exécution, on aurait ici dans une console python :
>>> mon_objet
['Nom;Prénom;Âge;Pseudo\n', 'Garcia;Serge;40;sergent_garcia\n', 'De la Vega;Diego;17;ZoRRo\n', 'McDuck;Scrooge;108;Picsou\n']
À noter la présence du caractère de saut de ligne \n, qui indique le changement de ligne tout en faisant
partie de la ligne.
Chaque enregistrement du fichier CSV donné en exemple est un quadruplet nommé représenté en python par un dictionnaire proposant quatre clefs. Le dernier enregistrement est donc le suivant :
{'Nom': 'McDuck', 'Prénom': 'Scrooge', 'Âge': '108', 'Pseudo': 'Picsou'}
Obtenir la liste des clés de l'objet sans ; et \n
La première ligne du fichier est le premier élément du tableau mon_objet.
premiere_ligne = mon_objet[0]
print(premiere_ligne)
Cette première ligne contient le saut de ligne '\n' que l'on voit en imprimant quelques caractères dessous.
On peut utiliser la méthode rstrip() pour le supprimer.
premiere_ligne = mon_objet[0]
print(premiere_ligne)
print('--')
chaine_des_descr = premiere_ligne.rstrip()
print(chaine_des_descr)
print('--')
Le résultat obtenu ressemble à cela :
Nom;Prénom;Âge;Pseudo
... que l'on peut découper pour obtenir une liste avec la méthode split() :
liste_clefs = chaine_des_descr.split(';')
ou en combinant les méthodes :
liste_clefs = mon_objet[0].rstrip().split(';')
Ainsi, on obtient :
['Nom', 'Prénom', 'Âge', 'Pseudo']
Manipulation de données au format .csv
Manipuler un nouveau fichier CSV
- Créer un fichier
table_films.csvà partir de la table film contenant qautre enregistrements et cinq descripteurs (nom, pays, année, genre et réalisateur). - Créer le programme Python
lecture_csv.pyde lecture de cette table permettant de lister l'objet Python complet et le 3è enregistrement, - Afficher enfin dans une liste les cinq descripteurs de la table.
Il s'agit finalement de refaire la partie de révisions appliquée à cette nouvelle table.
Fonction importer_csv()
À partir de maintenant, on reprend le fichier matable.csv de la section précédente (celui avec les pseudos).
On vous propose la fonction importer_csv() suivante :
def importer_csv(fichier_ouvert):
"""
...
"""
# On récupère les lignes du fichier
lignes=fichier_ouvert.readlines()
clefs=lignes[0].rstrip().split(';')
enregistrements=[] # On initialise la liste des enregistrements obtenus
for i in range(1,len(lignes)): # On parcourt...
valeurs=lignes[i].rstrip().split(';') # On extrait les valeurs
enregistrements.append({}) # On prépare le dctionnaire qui recueille les valeurs
for j in range(len(clefs)): # On parcourt les descripteur
enregistrements[i-1][clefs[j]]=valeurs[j] # On associe à chaque clef sa valeur
return clefs,enregistrements
Bien comprendre cette fonction et compléter le docstring de cette fonction, mais aussi les commentaires.
Détection d'un potentiel doublon
On se propose de s'inspirer de la fonction précédente pour créer une fonction pseudo_present() qui prend en
entrée un fichier (matable.csv via l'objet fichier_ouvert) et une chaîne de caractère pseudo, qui sera
notre pseudo à tester.
Si le pseudo est présent dans la table, on renvoie True, sinon False.
Compléter la fonction suivante (les ...) afin de réaliser cette opération :
def pseudo_present(fichier_ouvert,pseudo):
"""
Vérifie la présence d'un pseudo dans une table de comptes
"""
# On récupère les lignes
...
...: # On parcourt les lignes du fichier à partir de la deuxième (la première ce sont les descripteurs)
valeurs=... # On extrait les valeurs
if ...:
return True # On renvoie True si on trouve le pseudo
return False # Sinon, on n'a pas trouvé le pseudo
Lire une documentation
Nous allons utiliser une nouvelle méthode pour manipuler notre fichier :
with open('matable.csv','a',encoding='utf-8') as utilisateurs:
pass
À l'aide du terminal de Pyzo (ou d'un terminal Python), appeler l'aide de la méthode open. On pourra utiliser
pour cela help().
Donner la signification du paramètre 'a'.
Insérer un enregistrement
Compléter le code de la fonction inserer() ci-dessous. On n'utilisera que la fonction print pour écrire dans
le fichier.
Auparavant, vous aurez fait appel à l'aide de la fonction print() afin de prendre en compte le paramètre
sep, mais aussi file ; l'idée était bien sûr d'écrire (print()) dans le fichier_ouvert...
def inserer(fichier_ouvert, enregistrement):
"""
Insère un enregistrement à la fin d'un fichier csv
Paramètres :
fichier_ouvert : ficher csv ouvert en écriture, pointeur à la fin
enregistrement : dictionnaire représentant l'objet à enregistrer dans la table
Valeur renvoyée : None
"""
pass
Limites du CSV
Nous allons voir dans ces deux sous-parties, les limites de la manipulation de fichier CSV avec un langage de programmation tel que Python.
Un problème de validité des données
Créer un fichier utilisateurs.csv avec les descripteurs précédents : Nom, Prénom, Âge et Pseudo
Créer un module inscription.py en complétant le code ci-dessous, pour cela :
- Compléter le module, sous la ligne
if __name__=='__main__':dans le squelette ci-dessous, afin qu'à l'exécution, ce module- demande un pseudo,
- vérifie qu'il n'est pas dans la table
utilisateurs.csv, affiche Pseudo déjà utilisé et termine s'il y est, - demande le nom, le prénom et l'âge,
- inscrit l'utilisateur dans la table
utilisateurs.csv.
def pseudo_present(table, pseudo):
"""
Vérifie la présence d'un pseudo dans une table de comptes
"""
pass
def inserer(nom_fichier, clefs, enregistrement):
"""
Insère un enregistrement à la fin d'un fichier csv
Paramètres :
nom_fichier : chemin d'un fichier csv (chaine de caractères)
clefs : tableau des descripteurs du fichier csv
enregistrement : dictionnaire dont les clefs sont les éléments de clefs, auxquelle sont associées des chaines de caractères
Valeur renvoyée : None
"""
pass
if __name__=='__main__':
pseudo = input("Entrez votre pseudo : ")
# On importe la table utilisateur et on teste si le pseudo existe
...
if ...: # On vérifie la présence du pseudo
print("Pseudo déjà utilisé, désolé")
else: # On continue l'insctiption si le pseudo est disponible
nom = input("Entrez votre nom : ")
prénom = input("Entrez votre prénom : ")
age = input("Entrez votre âge : ")
# On crée le dictionnaire avec les informations
...
# On effectue l'inscription dans la table avec inserer()
...
print("Bienvenue.")
Simulations d'inscriptions parallèles
Imaginer les problèmes que peut poser ce système s’il est utilisé pour plusieurs inscriptions simultanées, par exemple sur un serveur.
- Ouvrir deux shells Python dans Pyzo.
- Dans le premier, lancer le programme puis saisir un pseudo, par exemple
'Roger'. - Passer au deuxième shell, lancer le programme, saisir le même pseudo puis terminer l'inscription
- Terminer l'inscription dans le premier terminal.
Observer le contenu de utilisateurs.csv ; que constatez-vous ? Expliquez...
Simulations d'inscriptions parallèles semi-automatisés
Créer un module simulation.py qui a le même fonctionnement, mais non interactif : il remplace les entrées
de l'utilisateur par le choix aléatoire d'une chaîne de caractères dans un tableau de cinq possibilités
On pourra utiliser la fonction choice() du module random pour le choix aléatoire dans une liste.
Ajouter un temps d'attente aléatoire après la vérification de la présence du pseudo (pour simuler une recherche plus longue dans une très grosse table).
Pour ce temps aléatoire, on peut donner en paramètre de la fonction sleep() du module time le nombre
0.5*random(), où random() est importée du module random, pour une attente d'une durée aléatoire
entre 0 et 500ms.
Utiliser une commande ou un script shell pour lancer en parallèle dix instances de ce programme. Constater encore une fois que l'unicité du pseudo n'est pas garantie. Sous Linux, on rappelle que :
- La commande
python3 simulation.pylance le programme et attend la fin de son exécution. - La commande
python3 simulation.py &lance le programme et rend immédiatement la main, ce qui permet de faire autre chose en parallèle de l'exécution du module python, si elle est encore en cours (uniquement sur Linux).
On peut alors utiliser la syntaxe suivante :
for i in {1..10}
do
MaCommande &
done
for /L %%i in (1,1,10) do (
start /b MaCommande
)
Attention ! Sur Windows, on veillera à indiquer les liens complets sous la forme : U:\\eleves\\..., dans le fichier
Python et dans la commande bat.
Un problème d'intégrité des données
On propose une parade simple au problème qui se pose dans la partie précédente : garder le fichier ouvert entre la recherche du pseudo et l'inscription finale, pour bloquer l'accès à la table entre ces deux étapes et ainsi garantir la validité de la vérification.
Obtenir la liste des modes d'ouverture utilisables en deuxième paramètre de open() et choisir le plus adapté à
notre nouveau besoin.
On évite les modes 'x', 'w' et 'a' qui ne conviennent pas. Dans notre cas, on choisit 'r+'. Explicitez
ce mode...
Effectuer une copie du module simulation.py qui s'appelle simulation2.py. Le modifier pour qu'il n'effectue
qu'une seule ouverture du fichier, en mode 'r+', au début du bloc if __name__=='__main__':, puis le ferme à la
fin de ce bloc avec .close().
Ajouter également, avec print(), des indications au début et à la fin de ce bloc, pour donner des indications
supplémentaires du bon traitement des données.
Exécuter 10 fois ce script en parallèle, comme précédemment. Qu'observe-t-on ?
Conclusion et une solution : les SGBD
Remarque
Dans cette activité, nous avons repéré de nombreux problèmes avec la manipulation des fichiers CSV. Aussi, nous vous proposons un SGBD pour répondre à ces besoins et assurer l'intégrité et la validité des données.
SGBD
Un Système de Gestion de Bases de Données permet de garantir l'intégrité des données, par exemple en prenant la forme d'un serveur qui centralise tous les accès à la base de données, et aussi leur validité, en traitant les demandes de consultation ou d'écriture sous la forme de requêtes qui effectuent des opérations de vérifications dictées par le schéma relationnel de la base de données.
Systèmes de Gestion de Bases de Données (SGBD)
Principes des SGBD
Après avoir consulté la vidéo, répondre aux questions ci-dessous :
- Pourquoi ne peut-on pas utiliser de fichiers CSV pour gérer une base de données ?
- Pourquoi utilise-t-on plusieurs serveurs pour stocker les mêmes données ?
- Qu'est-ce qu'un accès concurrent ?
- Quelle est la différence entre une base de données et un SGBD ?
- Quels services permet donc un SGBD ?
- Quel est l'intérêt d'utiliser un SGBD-R ? Quel langage utilise un SGBD-R ?
Prise en mais d'un SGBDR
Vous allez utiliser un logiciel permettant la mise en œuvre d'un SGBDR de façon simplifiée. Afin de le découvrir, suivez les étapes ci-dessous, et explorez de vous-même le logiciel. Vous devriez voir, lors de vos manipulations, une syntaxe ressemblant à un langage de programmation. Il s'agit du SQL ! Jetez-y un œil pour voir à quoi cela ressemble. Ce sera bientôt à vous d'écrire ce texte, et non à une interface graphique !
En utilisant le logiciel DB Browser, construire la base de données présente dans la capsule vidéo et dont le schéma relationnel est rappelé ci-dessous.
Préciser le type de chaque attribut de cette table.
Compléter ensuite la base avec les données de films et de réalisateur.
Conformément au schéma relationnel suivant, adapter votre base de données en créant deux nouvelles relations :
- Relation nationalité ou pays
- Relation genre
Alimenter enfin correctement cette base.


