diff --git a/seance3_4h/figures/schema_bdd_hotellerie.png b/seance3_4h/figures/schema_bdd_hotellerie.png index f481a66eb6bd201bdb9b297ab1b104552dc71160..f8911d1860eeeafaacf16363dcc0cbd40fbf1274 100644 Binary files a/seance3_4h/figures/schema_bdd_hotellerie.png and b/seance3_4h/figures/schema_bdd_hotellerie.png differ diff --git a/seance3_4h/seance3_4h.md b/seance3_4h/seance3_4h.md index 3c648b566f5a69dbd94adceb2bab91bbbdf9d855..979b066405a05214ef4ccdcb4ac3091aed311d97 100644 --- a/seance3_4h/seance3_4h.md +++ b/seance3_4h/seance3_4h.md @@ -4,7 +4,6 @@ # BE #3 : Exceptions et Base de données SQL ---- L'objectif principal de ce BE concerne l'utilisation **des exceptions** ([lien](https://docs.python.org/fr/3/tutorial/errors.html) officiel, [tuto _devstory_](https://devstory.net/11421/python-exception-handling) sur les exceptions) pour améliorer la robustesse d'un code. Pour expérimenter ce concept clé, nous nous servirons du prétexte de la manipulation de bases de données à l'aide de requêtes _SQL_ (_Structured Query Language_), écrites en _Python_. Ce BE est composé de 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_; @@ -40,11 +39,12 @@ Toutes les opérations sur une base de données de ce type peuvent être effectu 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... +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 en _Python_ (15 min.) @@ -132,8 +132,8 @@ if __name__ == '__main__': A priori, ce programme ne lance pas d'exception. Modifiez-le pour faire apparaître les 2 problèmes énoncés ci-dessus. Pour cela : - - Changez le nom de la bdd dans le programme, p. ex. _impossible.db_. Comment interprétez-vous le message d'erreur en observant le contenu de votre répertoire de travail ? - - Revenez au nom correct du fichier : _hotellerie.db_. Testez alors des noms erronés pour les tables, puis pour les champs. +- Changez le nom de la bdd dans le programme, p. ex. _impossible.db_. Comment interprétez-vous le message d'erreur en observant le contenu de votre répertoire de travail ? +- Revenez au nom correct du fichier : _hotellerie.db_. Testez alors des noms erronés pour les tables, puis pour les champs. On constate, dans chaque situation, que l'exception `sqlite3.OperationalError` est lancée, avec des messages d'information différents qui précisent le type d'erreur. Remplacez alors le code `except Exception as err:` par le code `except sqlite3.OperationalError as err:`, et vérifiez que cela fonctionne de la même manière que précédemment. @@ -162,35 +162,36 @@ Le constructeur (méthode *\_\_init\_\_(...)*) se chargera d'ouvrir une connexio _Remarques_ : - - Pour fermer correctement l'accès à la base de donnée, pensez à implémenter la méthode *\_\_del\_\_(...)* (vue en cours), qui est appelée automatiquement (et de manière implicite) par _Python_ lors de la destruction des objets de la classe. Typiquement : +- Pour fermer correctement l'accès à la base de donnée, pensez à implémenter la méthode *\_\_del\_\_(...)* (vue en cours), qui est appelée automatiquement (et de manière implicite) par _Python_ lors de la destruction des objets de la classe. Typiquement : ```python def __del__ (self): self.__conn.close() ``` - - La méthode `get_name_hotel_etoile(...)` se charge de retourner le résultat de la requête, mais ne se charge pas d'en afficher le résultat. L'affichage est laissé au programme principal, ici essentiellement pour contrôler le résultat. - - Pensez à intercepter les exceptions de type `sqlite3.OperationalError`, comme vu précédemment, et à renvoyer dans ce cas un résultat sous la forme d'une liste vide. +- La méthode `get_name_hotel_etoile(...)` se charge de retourner le résultat de la requête, mais ne se charge pas d'en afficher le résultat. L'affichage est laissé au programme principal, ici essentiellement pour contrôler le résultat. +- Pensez à intercepter les exceptions de type `sqlite3.OperationalError`, comme vu précédemment, et à renvoyer dans ce cas un résultat sous la forme d'une liste vide. __Améliorations à implémenter__ : - - Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile(-1)` dans le programme principal ? **Truc:** exception standard **ValueError** ou **AssertionError**. - - Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile("Hello")` ? **Truc:** exception standard **TypeError**. +- Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile(-1)` dans le programme principal ? **Truc:** exception standard **ValueError** ou **AssertionError**. +- Comment se comporte votre programme si on insère cet appel `aHotelDB.get_name_hotel_etoile("Hello")` ? **Truc:** exception standard **TypeError**. Veillez à ce que ces _appels erronés_ renvoient une liste vide tout simplement. + ### 2.2 Requête en écriture (45 min.) Créer une requête permettant d'ajouter un nouveau client et de renvoyer son identifiant (c'est à dire son _numclient_). Si le client existe déjà (même nom ET même prénom), la méthode renverra son _numclient_ (on supposera qu'il n'y a pas clients homonymes). Pour cette requête, renseignez-vous sur la commande `INSERT INTO`. _Attention_ la clé primaire sera renseignée automatiquement, pas besoin de la préciser explicitement. Notez également que l'attribut _curseur.lastrowid_ permet de récupérer le _numclient_ du nouveau client. 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 successives le même programme ; vous devriez alors retrouver le même numéro de client. + - soit en consultant la base avec `DB Browser for SQLite`; + - soit en exécutant par 2 fois successives le même programme ; vous devriez alors retrouver le même numéro de client. _Remarques_ : - - Pensez à quitter le logiciel `DB Browser for SQLite` avant d'exécuter votre programme. - - En cas de destruction de la base `Hotellerie.db` (les requêtes en écriture sont toujours plus dangereuses que les requêtes en lecture !), pensez à la télécharger à nouveau ! +- Pensez à quitter le logiciel `DB Browser for SQLite` avant d'exécuter votre programme. +- En cas de destruction de la base `Hotellerie.db` (les requêtes en écriture sont toujours plus dangereuses que les requêtes en lecture !), pensez à la télécharger à nouveau ! ---