Skip to content
Snippets Groups Projects
Commit d5765dec authored by Derrode Stéphane's avatar Derrode Stéphane :dromedary_camel:
Browse files

Publication Sujet BE #3

parent b168ab36
Branches
No related tags found
No related merge requests found
**Consignes pour le rendu**
Ce BE constitue le premier devoir à rendre pour INF-TC2. Le compte-rendu de ce travail devra être déposé sur l'espace de dépôt spécifique à votre groupe sur ``Pedagogie1``, dans un **délai de deux semaines après la séance** (délai de rigueur, aucun travail accepté au delà de cette date).
- Le travail peut être individuel ou en binôme.
- Le dépôt consistera en une unique archive (zip, rar) contenant l'ensemble des fichier suivants:
- la base de données *Hotellerie.db* dans l'état qu'elle a après exécution du programme principal. Ainsi que le fichier Python, appelé *HotelDB.py*, qui contiendra la classe **HotelDB** et un programme principal permettant de rejouer l'ensemble des requêtes de cet énoncé.
- la dernière partie vous propose de travailler éventuellement avec une autre base de données de votre choix : si vous choisissez cette option, n'oubliez pas d'inclure la nouvelle base de données et le programme Python qui réalise les requêtes que vous aurez imaginés.
- un rapport (format markdown ou pdf) contenant
- une en-tête où devront figurer de manière claire le nom des élèves, leur numéro de groupe, le nom de l'encadrant ainsi que le titre du BE.
- des commentaires sur la programmation de chacune des requêtes et les résultats obtenus.
- Vous pouvez insérer tout diagramme, toute figure ou toute explication que vous souhaitez, mais dans un **nombre de pages limité à 10** (il n'est pas demandé de rédiger 10 pages, c'est juste une limite à ne pas dépasser!).
- L'archive devra nécessairement porter le nom suivant : *nom1-devoir1.zip* ou *nom1-nom2-devoir1.zip* (pour les étourdis, pensez à remplacer *nom1* et *nom2* par vos propres noms :-) )
# Quelques exemples d'usage de la librairie matplotlib
# De nombreux exemples supplémentaires à cette adresse: https://matplotlib.org/gallery/index.html
# Remarque : N'oubliez pas plt.close()! après chaque figure
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
## function
#############################################
x = np.linspace(0, 2, 100) # Generate evenly spaced numbers
fig, ax = plt.subplots() # Create a figure and an axis.
ax.plot(x, x, label='linear') # Plot some data on the axes.
ax.plot(x, x**2, label='quadratic') # Plot more data on the axes...
ax.plot(x, x**3, label='cubic') # ... and some more.
ax.set_xlabel('x label') # Add an x-label to the axes.
ax.set_ylabel('y label') # Add a y-label to the axes.
ax.set_title("Simple Plot") # Add a title to the axes.
ax.legend() # Add a legend.
#plt.show() # Display the plot (close to continue)
plt.savefig('mpl_plot.png') # Save the plot on the HD (current directory)
plt.close() # Close the fig
## scatter data
#############################################
data1, data2 = np.random.randn(2, 100) # Draw random samples
fig, ax = plt.subplots(1, 1) # Create a figure and an axis.
ax.plot(data1, data2, marker='x') # Scatter plot
plt.savefig('mpl_scatter.png') # Save the plot on the HD
plt.close() # Close the fig
## error bar
# https://matplotlib.org/api/_as_gen/matplotlib.pyplot.errorbar.html
#############################################
x = np.linspace(0, 10, 50)
dy = 0.8
y = np.sin(x) + dy * np.random.randn(50)
plt.errorbar(x, y, yerr=dy, fmt='o', color='black', ecolor='lightgray', elinewidth=3, capsize=0);
plt.savefig('mpl_errorbar.png')
plt.close()
## histogram (avec personalisation)
# https://matplotlib.org/3.3.1/api/_as_gen/matplotlib.pyplot.hist.html
#############################################
x = np.random.randn(1000)
plt.style.use('classic')
fig=plt.figure(figsize=(5,3))
ax = plt.axes(facecolor='#E6E6E6')
# Afficher les ticks en dessous de l'axe
ax.set_axisbelow(True)
# Cadre en blanc
plt.grid(color='w', linestyle='solid')
# Cacher le cadre
# ax.spines contient les lignes qui entourent la zone où les
# données sont affichées.
for spine in ax.spines.values():
spine.set_visible(False)
# Cacher les marqueurs en haut et à droite
ax.xaxis.tick_bottom()
ax.yaxis.tick_left()
# Nous pouvons personnaliser les étiquettes des marqueurs
# et leur appliquer une rotation
marqueurs = [-3, -2, -1, 0, 1, 2]
xtick_labels = ['A', 'B', 'C', 'D', 'E', 'F']
plt.xticks(marqueurs, xtick_labels, rotation=30)
# Changer les couleur des marqueurs
ax.tick_params(colors='gray', direction='out')
for tick in ax.get_xticklabels():
tick.set_color('gray')
for tick in ax.get_yticklabels():
tick.set_color('gray')
# Changer les couleurs des barres
ax.hist(x, edgecolor='#E6E6E6', color='#EE6666')
plt.savefig('mpl_histopersonalise.png')
plt.close()
seance3_4h/figures/DBBrowser.png

266 KiB

seance3_4h/figures/schema_bdd_hotellerie.png

25.6 KiB

File added
**Sommaire**
[[_TOC_]]
# BE #3 : Base de données SQL
L'objectif de ce BE est d'expérimenter la manipulation (créer, lire, interroger, modifier) de bases de données relationnelles avec le langage SQL (*Structured Query Language*), à partir de Python. Le BE est décomposé en trois parties:
1. **La première partie** (durée: 45 min.) présente quelques commandes élémentaires pour interroger une base SQL à partir de Python;
1. **La seconde partie** (durée: 75 min.) permet de découvrir comment manipuler une base de données SQL avec Python. L'énoncé est rédigé sous une forme tutoriel;
1. **La troisième partie** (durée: 120 min. et +) constitue un travail plus personnalisé qui vous permettra de mettre à profit vos connaissances sur la programmation par tests, la gestion des exceptions, la librairie graphique *matplotlib* et bien sûr les bases de données SQL.
Ce BE fera l'objet d'un compte-rendu (CR), seul ou en binôme. Avant de commencer, veuillez prendre connaissance des consignes concernant le rendu du travail (à respecter scrupuleusement) qui se trouvent dans le fichier [consignes_BE#3.md](./consignes_BE#3.md) (dans le même répertoire que cet énoncé).
## 1. Mini-tutoriel sur la base Hotellerie.db (45 min.)
Le système de gestion de base de données qui sera utilisé pour la suite de ce BE est ``SQLite``. Ce système très simple fonctionne en stockant une base de données dans un fichier unique au format ``.sqlite``. La base de tests utilisée dans cette partie s'appelle *hotellerie.db* ; elle est disponible au même endroit que cet énoncé.
Le schéma de la base de données est le suivant:
<center><img src="figures/schema_bdd_hotellerie.png" style="width:50%"/></center>
La base est composée de 5 tables, ces tables étant composées d'un nombre variable de champs. Les champs soulignés représentent les clés primaires (ou *primary key (PK)* en anglais). En particulier, la clé primaire de la table **chambre** est composée des attributs *numchambre* et *numhotel* (cette dernière étant la clé primaire de la table **hotel**).
*Remarque* : Vous trouverez [ici, une vidéo](https://www.youtube.com/watch?v=VgTRNqn2fn0) qui montre comment utiliser [draw.io](https://app.diagrams.net) pour créer un diagramme entité-association. Il NE vous est PAS demandé de dessiner le diagramme de cette base de données.
### 1.1 DB browser for SQLite (30 min.)
Toutes les opérations sur une base de données de ce type peuvent être effectuées en Python via les classes et les méthodes présentes au sein du module ``sqlite3``. Pour manipuler de manière interactive le contenu de la base (créer, supprimer ou modifier des tables et des enregistrements, effectuer des requêtes SQL...), il existe des outils adaptés. L'outil retenu dans le cadre de ce cours s'appelle ``DB Browser for SQLite``. C'est un logiciel libre qui existe pour toutes les plate-formes : Windows, MacOs, nombreuses distributions Linux et Unix...
- Téléchargez et installez [DB Browser for SQLite](https://sqlitebrowser.org/) en suivant les instructions d'installation en fonction de votre système d'exploitation.
- Ouvrez la base *hotellerie.db* et naviguez dans les tables (onglet ``Structure de la Base de Données``) et les enregistrements (onglet ``Parcourir les données``) pour prendre connaissance de la base (telle qu'elle est schématisée dans la figure ci-dessus).
<center><img src="figures/DBBrowser.png" style="width:75%"/></center>
- Dans l'onglet ``Exécuter le SQL``, lancez la requête suivante
```SQL
SELECT nom, ville
FROM hotel;
```
La réponse apparaît sous forme de 12 lignes. Ça vous rappelle des choses ? Si non, alors voici quelques pointeurs pour vous rafraîchir la mémoire:
- [cours tutoriel sur SQL](https://www.1keydata.com/fr/sql/)
- [SQL : sélection, jointure, regroupement, filtre](http://cerig.pagora.grenoble-inp.fr/tutoriel/bases-de-donnees/chap20.htm)
- et tant d'autres...
### 1.2 Quelques requêtes Python (15 min.)
Nous allons maintenant chercher à reproduire la requête en utilisant Python et le package ``sqlite3``. C'est une librairie objet dont la [documentation](https://docs.python.org/3/library/sqlite3.html#module-sqlite3) fournit une description des classes et des méthodes disponibles. Suivez le guide...
Le squelette typique d'un tel programme s'écrit:
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db') # connexion à la bdd
# travail sur la bdd à partir du connecteur
conn.commit() # pour enregistrer les éventuels changements
conn.close() # pour fermer proprement l'accès à la base
```
Ainsi, pour obtenir la réponse à la requête précédente:
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db')
curseur = conn.cursor() # objet permettant de faire des requêtes
curseur.execute("SELECT nom, ville FROM hotel;") # requête SQL
ligne1 = curseur.fetchone() # 1ère ligne résultat de la requête
print('ligne1 =', ligne1)
ligneAll = curseur.fetchall() # toutes les lignes de la requête
print('ligneAll =', ligneAll)
conn.close()
```
Copiez et exécutez ce programme ; le résultat se présente sous forme d'un tuple, ou sous forme d'une liste de tuples. Ainsi la commande
```python
print(ligneAll[0][0])
```
imprime le nom du premier hôtel qui apparaît dans la liste des résultats de la requête.
Voici un usage intéressant à étudier:
```python
import sqlite3
if __name__ == '__main__':
conn = sqlite3.connect('hotellerie.db')
curseur = conn.cursor()
for ligne in curseur.execute("SELECT * FROM hotel WHERE etoiles=3"):
print('ligne=', ligne)
conn.close()
```
-----
## 2. Classe HotelDB (75 min.)
Il s'agit de créer une classe **HotelDB** permettant de réaliser un certain nombre de requêtes et de mises à jour de la base *Hotellerie.db*.
### 2.1 Requête en lecture (30 min.)
Dans un fichier *HotelDB.py*, commencez à développer la classe permettant de répondre à ce programme principal dont l'objectif est d'afficher le nom des hôtels 2 étoiles (noter que le nombre d'étoiles est passé en argument):
```python
if __name__ == '__main__':
aHotelDB = HotelDB('hotellerie.db')
print(aHotelDB.get_name_hotel_etoile(2))
```
*Remarque* : Pour fermer correctement l'accès à la base de donnée, pensez à implémenter la méthode ``__del__(self)`` (vue en cours), qui est appelée automatiquement par Python lorsque l'objet est détruit.
*Améliorations* : Comment se comporte votre programme si on insère dans le programme ci-dessus la commande ``print(aHotelDB.get_name_hotel_etoile(-1))``? Et la commande ``print(aHotelDB.get_name_hotel_etoile("Hello"))``. Comment éviter que cet usage ne produise la fin brutale du programme et renvoie une liste vide tout simplement?
### 2.2 Requête en écriture (45 min.)
Créer une requête permettant d'ajouter un nouveau client. Si le client existe déjà (même nom ET même prénom), la méthode renverra le numéro de ce client. Si le client n'existe pas, alors la méthode créera un nouveau client, en lui adjoignant le premier numéro non encore utilisé (c'est une clé primaire !). Pour cela, renseignez-vous sur la commande ``INSERT INTO``. Vérifier que le nouveau client a bien été sauvegardé dans le fichier *Hotellerie.db*:
- soit en consultant la base avec ``DB Browser for SQLite``;
- soit en exécutant par 2 fois le même programme, vous devriez retrouver le même numéro de client.
-----
## 3. Requêtes libres (120 min. et +)
Dans cette dernière partie, nous vous invitons à imaginer et implémenter **DEUX (2)** requêtes originales à partir de la bdd *Hotellerie.db*, ou de tout autre bdd que vous aurez trouvée sur Internet. Voici un exemple de site proposant des bdd SQL gratuites (il y en a beaucoup d'autres) : [bases-donnees-gratuites](https://sql.sh/categorie/bases-donnees-gratuites). Dans le second cas, n'oubliez pas d'inclure cette base dans votre archive, et de préciser dans votre rapport le chemin pour la télécharger.
*Quelques conseils*:
* Imaginez deux requêtes originales à partir de la base que vous avez sélectionnée. N'hésitez pas à visiter un site de réservation d'hôtels pour trouver des idées de requêtes intéressantes.
* Concevez des exemples de requêtes ainsi que les résultats qu'elles doivent renvoyer (il est recommandé de les rédiger sous forme de tests unitaires).
* Implémentez les méthodes gérant vos deux requêtes (éventuellement dans une nouvelle classe calquée sur le modèle de la classe **HotleDB** si vous décidez d'utiliser une seconde bdd).
Les deux requêtes doivent être relativement sophistiquées (pas de simples ``select ... from``), l'évaluation de cette partie dépendra :
- de l'originalité de vos requêtes, et
- de la valorisation graphique des résultats de vos requêtes à l'aide de la librairie **matplotlib**.
- de leur présentation dans le rapport.
À titre d'exemples, vous trouverez, à côté de cet énoncé, un fichier nommé ``ex_matplotlib.py``. L'exécution de ce script génère 4 figures dans le répertoire *figures*. Inspirez-vous largement de ce programme pour vos propres figures. *Conseil*: Évitez de vous lancer dans des requêtes avec des données géographiques, genre ```trouver tous les hôtels à moins de 5 kilomètres``` car l'usage de cartes géographiques dépasse les attentes de ce qui est demandé ici.
......@@ -4,7 +4,7 @@ Comme tout tutoriel, ce document a besoin de vos retours pour s'améliorer! N’
# Tuto sur git/gitlab
Ce document présente un tuto à l'usage de **git**/**gitlab**. Il est (sera?) consultable sous forme de vidéo dans le Moodle du cours INF-TC2.
Ce document présente un tuto à l'usage de **git**/**gitlab**. Il est consultable sous forme de vidéo sur le Moodle du cours, à ladresse https://pedagogie1.ec-lyon.fr/course/view.php?id=969.
## Installer **git** et *Github Desktop*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment