
PROJETS PERSONNELS : Scripting Python
Hello !
Ici je publie des scripts développés avec Python au fur et à mesure de mon apprentissage.
Le script le plus récent sera toujours en tête de page.
Le gestionnaire de listes avec base de données et interface graphique
Refonte du gestionnaire de listes vu précédemment mais cette fois-ci avec une interface graphique. Je voulais faire une sorte de mini chat bot où l’utilisateur choisit ce qu’il veut faire et l’application lui répond.
La prochaine amélioration sera de laisser l’utilisateur créer le type de liste qu’il veut.
Exemple d’exécution :








from lib import *from PySide6 import QtWidgets, QtCorefrom PySide6.QtCore import QTimer class App(QtWidgets.QWidget): """ Application de gestion de listes avec interface graphique. Attributs: current_state (str): État actuel de l'application. current_list (Liste): Liste en cours de gestion. bdcourses (bool): Indicateur de la base de données des courses. bdtaches (bool): Indicateur de la base de données des tâches. liste_de_courses (Liste): Liste des courses. liste_de_taches (Liste): Liste des tâches. """ def __init__(self): super().__init__() self.current_state = "initial" # État initial self.current_list = None # Liste en cours de gestion self.setWindowTitle("Gestionnaire de listes") self.setup_ui() self.setup_css() self.setup_connections() self.lancement() # Déclarez ces variables comme attributs de la classe self.bdcourses = False self.bdtaches = False self.liste_de_courses = None self.liste_de_taches = None def setup_ui(self): """Configure l'interface utilisateur.""" self.layout = QtWidgets.QVBoxLayout(self) self.la_cmd = QtWidgets.QLabel() self.le_user = QtWidgets.QLineEdit() self.la_cmd.setText("Bienvenue !\n Taper 'ok' pour commencer.") self.layout.addWidget(self.la_cmd) self.layout.addWidget(self.le_user) self.la_cmd.setMinimumWidth(300) self.la_cmd.setMinimumHeight(400) def setup_connections(self): """Connecte les signaux aux méthodes appropriées.""" self.le_user.returnPressed.connect(self.reponse) self.le_user.textChanged.connect(self.mettre_a_jour_texte) def mettre_a_jour_texte(self, texte): """ Met à jour l'attribut texte_utilisateur à chaque modification """ self.texte_utilisateur = texte.strip().lower() def setup_css(self): """Configure les styles CSS de l'interface.""" self.setStyleSheet(""" background-color: rgb(30, 30, 30); color: rgb(240, 240, 240); border: 0; """) self.la_cmd.setStyleSheet("color: rgb(255, 255, 255);") self.le_user.setStyleSheet("background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);") def mettre_a_jour_interface(self, message, focus=True): """Met à jour l'interface utilisateur. Args: message (str): Message à afficher. focus (bool): Indique si le focus doit être remis sur le champ de texte. """ self.la_cmd.setText(message) self.la_cmd.adjustSize() self.le_user.clear() if focus: self.le_user.setFocus() def gerer_liste(self, liste): """Gère la liste sélectionnée par l'utilisateur. Args: liste (Liste): Liste à gérer. """ tmp = self.affiche_menu() self.mettre_a_jour_interface(tmp) self.current_state = "gestion_liste" def affiche_menu(self): """Renvoie le texte du menu d'options.""" actions = [ "Ajouter un élément", "Retirer un élément", "Afficher les éléments", "Vider la liste", "Revenir au menu principal" ] return "\n".join([f"{i+1} : {action}" for i, action in enumerate(actions)]) def process_reponse(self, liste): """ Affiche le 2ème menu et gère la réponse de l'utilisateur. Args: liste (Liste): Liste à gérer. """ choix_process_reponse = self.texte_utilisateur print(f"Choix de gestion : {choix_process_reponse}") if choix_process_reponse == "1": self.mettre_a_jour_interface("Ajoutez un élément à la liste :") self.current_state = "ajout_element" elif choix_process_reponse == "2": self.mettre_a_jour_interface("Retirez un élément de la liste :") self.current_state = "retrait_element" elif choix_process_reponse == "3": self.afficher_liste(liste) message = liste.afficher() self.mettre_a_jour_interface(f"{message}\nAppuyez sur 'Entrée' pour revenir au menu.") self.current_state = "afficher_liste" elif choix_process_reponse == "4": self.vider_liste(liste) self.mettre_a_jour_interface("La liste a été vidée.\nAppuyez sur 'Entrée' pour revenir au menu.") self.current_state = "gestion_liste" elif choix_process_reponse == "5": self.mettre_a_jour_interface("Retour au menu principal.\n\n Taper 'ok' pour commencer.") self.current_state = "initial" else: # Construire le message d'options à afficher tmp = self.affiche_menu() self.mettre_a_jour_interface(f"Option invalide. Réessayez.\n\n{tmp}") def vider_liste(self, liste): """ Vide la liste. """ liste.effacer() def process_ajout(self, liste): """ Demande à l'utilisateur un élément à ajouter à la liste. """ element_ajout = self.le_user.text().strip() # Récupérer et nettoyer l'entrée utilisateur if not element_ajout: self.mettre_a_jour_interface("L'élément à ajouter est vide. Veuillez entrer un élément.") return # Ne pas continuer tant que l'utilisateur n'a pas saisi quelque chose # Ajouter l'élément à la liste liste.ajouter(element_ajout) message = f"L'élément '{element_ajout}' a bien été ajouté à la liste." self.mettre_a_jour_interface(message) self.current_state = "gestion_liste" # Supprimer tous les anciens signaux pour éviter les doublons try: self.le_user.returnPressed.disconnect() except TypeError: pass # Reconnecter pour retourner au menu en appuyant sur Entrée self.le_user.returnPressed.connect(lambda: self.gerer_element(liste)) def process_retrait(self, liste): """ Demande à l'utilisateur un élément à retirer de la liste. """ element_a_retirer = self.le_user.text().strip() # Récupérer et nettoyer l'entrée utilisateur if not element_a_retirer: self.mettre_a_jour_interface("Veuillez entrer un élément.") return # Ne pas continuer tant que l'utilisateur n'a pas saisi quelque chose # Ajouter l'élément à la liste liste.enlever(element_a_retirer) message = f"L'élément '{element_a_retirer}' a bien été retirer de la liste." self.mettre_a_jour_interface(message) self.current_state = "gestion_liste" # Supprimer tous les anciens signaux pour éviter les doublons try: self.le_user.returnPressed.disconnect() except TypeError: pass # Reconnecter pour retourner au menu en appuyant sur Entrée self.le_user.returnPressed.connect(lambda: self.gerer_element(liste)) def afficher_liste(self, liste): """Affiche la liste dans l'interface Args: liste (Liste): Une liste instance de la classe Liste """ self.mettre_a_jour_interface(liste.afficher()) def gerer_element(self, liste): """Teste si la liste est vide ou non et appelle la méthode gerer_liste Args: liste (Liste): Une liste instance de la classe Liste """ if liste.taille() == 0: print("Votre liste est vide.") else: print(liste.afficher()) return self.gerer_liste(liste) def lancement(self): """ Lance le programme et attend la réponse de l'utilisateur pour naviguer dans les options. """ self.mettre_a_jour_interface("Bienvenue !\n Taper 'ok' pour commencer.") def reponse(self): """Traite la réponse de l'utilisateur et se connecte aux bases de données selon l'état actuel.""" choix_reponse = self.texte_utilisateur if self.current_state == "initial": if choix_reponse == "ok" or choix_reponse == "5": self.mettre_a_jour_interface( "Que voulez-vous faire ?\n (1) - Gérer ma liste de courses\n (2) - Gérer ma liste de tâches\n (3) - Quitter" ) self.current_state = "choix_liste" else: self.mettre_a_jour_interface("Commande inconnue. Tapez 'ok' pour commencer.") elif self.current_state == "choix_liste": if choix_reponse == "1": try: conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute("SELECT * FROM courses") donnees_courses = c.fetchall() conn.commit() conn.close() if donnees_courses: self.liste_de_courses = Liste("courses") for row in donnees_courses: self.liste_de_courses.ajouter(row[0]) self.bdcourses=True except sqlite3.Error as e: self.bdcourses = False # Créer la liste de courses si elle n'existe pas encore if not self.bdcourses: self.liste_de_courses = Liste("courses") # Crée une nouvelle liste de courses self.bdcourses = True # Marquer la liste comme créée #self.afficher_liste(self.liste_de_courses) message = self.liste_de_courses.afficher() self.current_list = self.liste_de_courses message += f"\nVous avez choisi de gérer votre liste de courses.\nTapez 'Entrer' pour continuer." self.mettre_a_jour_interface(message) self.gerer_element(self.liste_de_courses) elif choix_reponse == "2": try: conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute("SELECT * FROM taches") donnees_taches = c.fetchall() conn.commit() conn.close() if donnees_taches: self.liste_de_taches = Liste("taches") for row in donnees_taches: self.liste_de_taches.ajouter(row[0]) self.bdtaches=True except: self.bdtaches = False # Créer la liste de taches si elle n'existe pas encore if not self.bdtaches: self.liste_de_taches = Liste("taches") # Crée une nouvelle liste de taches self.bdtaches = True # Marquer la liste comme créée #self.afficher_liste(self.liste_de_courses) message = self.liste_de_taches.afficher() message += f"\nVous avez choisi de gérer votre liste de taches.\nTapez 'Entrer' pour continuer." self.mettre_a_jour_interface(message) self.current_list = self.liste_de_taches self.gerer_element(self.liste_de_taches) elif choix_reponse == "3": self.mettre_a_jour_interface("Quitter le programme.") QtCore.QTimer.singleShot(1000, self.close) else: self.mettre_a_jour_interface("Choix invalide. Essayez encore.\n\nQue voulez-vous faire ?\n (1) - Gérer ma liste de courses\n (2) - Gérer ma liste de tâches\n (3) - Quitter") elif self.current_state == "gestion_liste": self.process_reponse(self.current_list) elif self.current_state == "ajout_element": element = self.le_user.text().strip() if element: self.current_list.ajouter(element) self.mettre_a_jour_interface(f"L'élément '{element}' a bien été ajouté.") self.current_state = "gestion_liste" self.gerer_liste(self.current_list) elif self.current_state == "retrait_element": element = self.le_user.text().strip() if element: self.current_list.enlever(element) self.mettre_a_jour_interface(f"L'élément '{element}' a bien été retiré.") self.current_state = "gestion_liste" self.gerer_liste(self.current_list) elif self.current_state == "afficher_liste": self.gerer_liste(self.current_list) app = QtWidgets.QApplication([])win = App()win.show()app.exec()Le Ciné Club
Un petit gestionnaire de films avec interface graphique. On peut ajouter des films dans une liste stockée dans un fichier json ou supprimer des films de la liste.
Exemple d’exécution :
Fichier movie.py
import osimport jsonimport loggingCUR_DIR = os.path.dirname(__file__)DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")def get_movies(): with open(DATA_FILE, "r") as f: movie_list = json.load(f) return [Movie(movie_title) for movie_title in movie_list]class Movie(str): def __init__(self, movie_title): self.movie_title = movie_title.title() def __str__(self) -> str: return self.movie_title def _getMovies(self): with open(DATA_FILE, "r") as f: movie_list = json.load(f) return movie_list def _write_movies(self, movies): with open(DATA_FILE, "w") as f: json.dump(movies, f, indent = 4) def add_to_movies(self): # Récupérer la liste des films movies = self._getMovies() # Vérifier que le film n'est pas déjà dans la liste if self.movie_title not in movies: # Il n'y est pas, on l'ajoute movies.append(self.movie_title) self._write_movies(movies) return True else: # Il y est. On affiche un message logging.warning(f"{self.movie_title} est déjà dans la liste de films.") return False def remove_from_movies(self): # Récupérer la liste des films movies = self._getMovies() # Vérifier si le film est dans la liste if self.movie_title in movies: # Si c'est le cas, enlever le film movies.remove(self.movie_title) self._write_movies(movies)from PySide6 import QtWidgets, QtCorefrom movie import *class App(QtWidgets.QWidget): def __init__(self): super().__init__() self.setWindowTitle("Ciné Club") self.setup_ui() self.setup_css() self.setup_connections() self.populate_movies() def setup_ui(self): self.layout = QtWidgets.QVBoxLayout(self) self.lne = QtWidgets.QLineEdit() self.btn_add = QtWidgets.QPushButton("Ajouter un film") self.lst = QtWidgets.QListWidget() self.btn_del = QtWidgets.QPushButton("Supprimer le(s) film(s)") self.lst.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection) self.layout.addWidget(self.lne) self.layout.addWidget(self.btn_add) self.layout.addWidget(self.lst) self.layout.addWidget(self.btn_del) def setup_connections(self): self.btn_add.clicked.connect(self.add_movie) self.btn_del.clicked.connect(self.del_movie) self.lne.returnPressed.connect(self.add_movie) def setup_css(self): self.setStyleSheet(""" background-color: rgb(30, 30, 30); color: rbg(240, 240, 240); border: 0; """) self.lne.setStyleSheet("background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);") self.btn_add.setStyleSheet("color: rgb(255, 255, 255);") self.lst.setStyleSheet("background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);") self.btn_del.setStyleSheet("color: rgb(255, 255, 255);") def populate_movies(self): movies = get_movies() self.lst.addItems([m.movie_title for m in movies]) def add_movie(self): if self.lne.displayText() != "": movie = Movie(self.lne.displayText()) if movie.add_to_movies(): self.lst.addItem(movie.movie_title) self.lst.sortItems() print(f"Film ajouté : {self.lne.displayText()}") self.lne.setText("") return True else: self.lne.setText("") return False print("Le champ est vide.") return False def del_movie(self): if self.lst.selectedItems(): selected_movies = [i.text() for i in self.lst.selectedItems()] for m in selected_movies: movie = Movie(m) movie.remove_from_movies() # Recherche l'élément correspondant dans la QListWidget et le supprime items = self.lst.findItems(m, QtCore.Qt.MatchExactly) for item in items: self.lst.takeItem(self.lst.row(item)) # Supprime l'élément de la liste print(f"Film {movie.movie_title} supprimé") return True print("Aucun film n'est seléctionné.") return Falseapp = QtWidgets.QApplication([])win = App()win.show()app.exec()Le convertisseur de devises
Le classique convertisseur de devises qui convertit toutes devises.
Exemple d’exécution
from PySide6 import QtWidgetsimport currency_converterclass App(QtWidgets.QWidget): def __init__(self): super().__init__() self.c = currency_converter.CurrencyConverter() self.setWindowTitle("Convertisseur de devises") self.setup_ui() self.set_default_values() self.setup_css() self.setup_connections() def setup_ui(self): self.layout = QtWidgets.QHBoxLayout(self) self.cbb_devisesFrom = QtWidgets.QComboBox() self.spn_montant = QtWidgets.QSpinBox() self.cbb_devisesTo = QtWidgets.QComboBox() self.spn_montantConverti = QtWidgets.QSpinBox() self.btn_inverser = QtWidgets.QPushButton("Inverser devises") self.layout.addWidget(self.cbb_devisesFrom) self.layout.addWidget(self.spn_montant) self.layout.addWidget(self.cbb_devisesTo) self.layout.addWidget(self.spn_montantConverti) self.layout.addWidget(self.btn_inverser) self.cbb_devisesFrom.setMinimumHeight(10) self.cbb_devisesFrom.setMinimumWidth(50) self.cbb_devisesTo.setMinimumWidth(50) def set_default_values(self): self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies))) self.cbb_devisesTo.addItems(sorted(list(self.c.currencies))) self.cbb_devisesFrom.setCurrentText("EUR") self.cbb_devisesTo.setCurrentText("EUR") self.spn_montant.setRange(1, 1000000000) self.spn_montantConverti.setRange(1, 1000000000) self.spn_montant.setValue(100) self.spn_montantConverti.setValue(100) def setup_connections(self): self.cbb_devisesFrom.activated.connect(self.compute) self.cbb_devisesTo.activated.connect(self.compute) self.spn_montant.valueChanged.connect(self.compute) self.btn_inverser.clicked.connect(self.inverser_devises) def setup_css(self): self.setStyleSheet(""" background-color: rgb(30, 30, 30); color: rbg(240, 240, 240); border: 0; """) self.cbb_devisesFrom.setStyleSheet("color: rgb(255, 255, 255);") self.cbb_devisesTo.setStyleSheet("color: rgb(255, 255, 255);") self.spn_montant.setStyleSheet("color: rgb(255, 255, 255);") self.spn_montantConverti.setStyleSheet("color: rgb(255, 255, 255);") self.btn_inverser.setStyleSheet("color: rgb(255, 255, 255);") def compute(self): montant = self.spn_montant.value() devise_from = self.cbb_devisesFrom.currentText() devise_to = self.cbb_devisesTo.currentText() try: resultat = self.c.convert(montant, devise_from, devise_to) except currency_converter.currency_converter.RateNotFoundError: print("La convertion n'a pas fonctionné.") else: self.spn_montantConverti.setValue(resultat) def inverser_devises(self): devise_from = self.cbb_devisesFrom.currentText() devise_to = self.cbb_devisesTo.currentText() self.cbb_devisesFrom.setCurrentText(devise_to) self.cbb_devisesTo.setCurrentText(devise_from) self.compute()app = QtWidgets.QApplication([])win = App()win.show()app.exec()Un CRM en POO et avec une base de données tinyDB
Un gestionnaire d’utilisateurs aléatoires générés avec le module Faker et sauvegardés dans une base de données tinydb, enregistrée dans un fichier .json.
Exemple d’exécution du programme:
import reimport stringfrom tinydb import TinyDB, wherefrom pathlib import Pathclass User(): DB = TinyDB(Path(__file__).resolve().parent / 'db.json', indent=4) def __init__(self, first_name: str, last_name: str, phone_number: str="", adress: str="" ): self.first_name = first_name self.last_name = last_name self.phone_number = phone_number self.adress = adress def __repr__(self) -> str: return f"User({self.first_name}, {self.last_name})" def __str__(self): return(f"{self.full_name}\n{self.phone_number}\n{self.adress}") @property def full_name(self): return f"{self.first_name} {self.last_name}" @property def db_instance(self): return User.DB.get((where('first_name') == self.first_name) & (where('last_name') == self.last_name)) def _checks(self): self._check_names() self._check_phone_number() def _check_phone_number(self): phone_number = re.sub(r"[+()\s]*", "", self.phone_number) if len(phone_number) < 10 or not phone_number.isdigit(): raise ValueError(f"Numéro de téléphone {self.phone_number} invalide.") def _check_names(self): if not self.first_name and self.last_name: raise ValueError("Le prénom et le nom de famille ne peuvent pas être vide.") special_characters = string.punctuation + string.digits for character in self.first_name + self.last_name: if character in special_characters: raise ValueError(f"Nom invalide {self.full_name}.") def exists(self): return bool(self.db_instance) def delete(self) -> list[int]: if self.exists(): return User.DB.remove(doc_ids=[self.db_instance.doc_id]) return [] def save(self, validate_data: bool=False) -> int: if validate_data: self._checks() if self.exists(): return -1 else: return User.DB.insert(self.__dict__) def get_all_users(): return [User(**user) for user in User.DB.all()]if __name__ == "__main__": from faker import Faker fake = Faker(locale="fr_FR") for _ in range(10): user = User(first_name=fake.first_name(), last_name=fake.last_name(), phone_number=fake.phone_number(), adress=fake.address()) print(user.save()) print(user.__str__()) print("-"*20)Le gestionnaire de listes en POO
Un gestionnaire de listes qui reprend la base du script de la liste de courses, présentée précédemment.
Pour cet exemple, j’utiliserai la Programmation Orientée Objet en créant mes propres objets de classe Liste() qui hériteront de la classe list(). J’utilise aussi les bases de données SQL avec le module sqlite3 pour enregistrer les listes.
Dans ce programme, on ne gère que 2 systèmes de listes : la liste de courses et la liste de taches. La prochaine étape sera de demander à l’utilisateur le type de listes qu’il souhaite enregistrer.
On commence avec le script de constantes : constants.py
import osCUR_DIR = os.path.dirname(os.path.abspath(__file__))DATA_DIR = os.path.join(CUR_DIR, "data")DATABASE = os.path.join(DATA_DIR, "database.db")
import jsonimport loggingimport osimport sqlite3from constants import *LOGGER = logging.getLogger()class Liste(list): def __init__(self, nom): self.nom = nom def sauvegarder(self): if not os.path.exists(DATA_DIR): os.makedirs(DATA_DIR) conn = sqlite3.connect(DATABASE) table_name = self.nom c = conn.cursor() c.execute(f""" CREATE TABLE IF NOT EXISTS {table_name} ( element text ) """) c.execute(f"DELETE FROM {table_name}") for el in self: c.execute(f"INSERT INTO {table_name} (element) VALUES (?)", (el,)) conn.commit() conn.close() return True def ajouter(self, element): if not isinstance(element, str): raise ValueError("Vous ne pouvez ajouter que des chaines de caractères!") if element in self: LOGGER.error(f"{element} est déjà dans la liste.") return False else: self.append(element) self.sauvegarder() return True def enlever(self, element_a_supprimer): if element_a_supprimer in self: self.remove(element_a_supprimer) table_name = self.nom conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute(f"DELETE FROM {table_name} WHERE element=?", (element_a_supprimer,)) conn.commit() conn.close() return True return False def afficher(self): print(f"\nMa liste de {self.nom} : ") print("_"*50+"\n") for element in self: print(f" - {element}") print("_"*50+"\n") return True def effacer(self): self.clear() conn = sqlite3.connect(DATABASE) table_name = self.nom c = conn.cursor() c.execute(f"DELETE FROM {table_name}") conn.commit() conn.close() return True def taille(self): return len(self)from lib import *actions = [ "Ajouter un élément à la liste", "Retirer un élément de la liste", "Afficher les éléments de la liste", "Vider la liste", "Revenir au menu principal"]valide = Falsebdcourses = Falsebdtaches = Falsedef gerer_liste(liste): choix = 0 element="" while choix !=5 : print("\nChoisissez parmi les 5 options suivantes :\n") for i, element in enumerate(actions): print(f"{i+1} : {element}") reponse = input("Votre choix : ") if reponse.isdigit() : choix = int(reponse) else : print("Vous devez taper un chiffre !\n") continue if choix == 1 : article = input("Que souhaitez-vous ajouter à la liste ? ") if liste.ajouter(article): print(f"L'élément '{article}' a bien été ajouté à la liste.\n") elif choix == 2 : article = input("Quel élément souhaitez-vous retirer ? ") if article in liste : liste.enlever(article) print(f"L'élément '{article}' a bien été retiré de la liste.\n") else : print(f"L'élément '{article}' n'est pas dans la liste.\n") elif choix == 3 : liste.afficher() elif choix == 4 : liste.effacer() print("La liste a été vidée.\n") elif choix == 5: break else: print("Je n'ai pas compris. Veuillez recommencez.\n") continue return Truedef gerer_element(liste): if liste.taille() == 0: print("Votre liste est vide.") else: liste.afficher() return gerer_liste(liste)
while not valide: reponse = input("Que voulez-vous faire ? \n\t (1) - Gérer ma liste de courses \n\t (2) - Gérer ma liste de taches \n\t (3) - Quitter le programme \n Votre choix : ") if not reponse.isdigit(): print("\nVous devez saisir un chiffre.\n") continue else: if int(reponse) > 3: print("\nVous devez saisir un chiffre valide.\n") else: try: conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute("SELECT * FROM courses") donnees_courses = c.fetchall() conn.commit() conn.close() if donnees_courses: liste_de_courses = Liste("courses") for row in donnees_courses: liste_de_courses.ajouter(row[0]) bdcourses=True except: bdcourses = False try: conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute("SELECT * FROM taches") donnees_taches = c.fetchall() conn.commit() conn.close() if donnees_taches: liste_de_taches = Liste("taches") for row in donnees_taches: liste_de_taches.ajouter(row[0]) bdtaches=True except: bdtaches = False if int(reponse) == 1: if not bdcourses: liste_de_courses = Liste("courses") print(f"La liste de {liste_de_courses.nom} est créée.") gerer_element(liste_de_courses) elif int(reponse) == 2: if not bdtaches: liste_de_taches = Liste("taches") print(f"La liste de {liste_de_taches.nom} est créée.") gerer_element(liste_de_taches) else: print("Bye ! ") breakLa liste de courses en POO
Refonte du script de la liste de courses (ou autres listes) en programmation orientée objet (POO).
Le fichier principal : lib.py
import jsonimport loggingimport osfrom constants import DATA_DIRLOGGER = logging.getLogger()class Liste(list): def __init__(self, nom): self.nom = nom def ajouter(self, element): if not isinstance(element, str): raise ValueError("Vous ne pouvez ajouter que des chaines de caractères!") if element in self: LOGGER.error(f"{element} est déjà dans la liste.") return False self.append(element) return True def enlever(self, element): if element in self: self.remove(element) return True return False def afficher(self): print(f"Ma liste de {self.nom} : ") for element in self: print(f" - {element}") def sauvegarder(self): chemin = os.path.join(DATA_DIR, f"{self.nom}.json") if not os.path.exists(DATA_DIR): os.makedirs(DATA_DIR) with open(chemin, "w") as f: json.dump(self, f, indent=4) return Trueif __name__ == "__main__": liste = Liste("courses") liste.ajouter("Pommes") liste.ajouter("Poires") liste.afficher() liste.sauvegarder()import osCUR_DIR = os.path.dirname(os.path.abspath(__file__))DATA_DIR = os.path.join(CUR_DIR, "data")print(DATA_DIR)La liste de prénoms
Script qui récupère une liste de prénoms à l’intérieur d’un fichier .txt, la nettoie (enlève les points, virgules et espaces superflus), la trie par ordre alphabétique, et la sauvegarde à nouveau dans le fichier.
from pathlib import Pathimport osSOURCE_DIR = Path(__file__).resolve().parent / "prenoms.txt"liste_prenoms=[]liste_clean=[]if os.path.exists(SOURCE_DIR): with open(SOURCE_DIR, "r") as f: lines = f.read().splitlines()for i in lines: liste_prenoms.extend(i.split())liste_clean = sorted([prenom.strip(",. ") for prenom in liste_prenoms])with open(SOURCE_DIR, "w") as f: f.write("\n".join(liste_clean))Le trieur de fichiers et dossiers
Un petit script, utilisant le module ‘pathlib’, qui permet de faire du tri dans le dossier ‘Téléchargements’ de Windows, en créant des sous-dossiers en fonctions du type de fichiers présents (Images, Documents, Vidéos, etc), dans un unique dossier nommé ‘DATA’.
from pathlib import PathSOURCE_FILE =Path(r"C:\Users\***\Downloads") #remplacer *** par le nom utilisateur sur windowsDATA_DIR = SOURCE_FILE / "DATA"DATA_DIR.mkdir(exist_ok=True)dirs = {".png": "Images", ".jpg": "Images", ".jpeg": "Images", ".gif": "Images", ".wav": "Music", ".m4a": "Music", ".mp4": "Videos", ".mov": "Videos", ".zip": "Archives", ".rar": "Archives", ".pdf": "Documents", ".txt": "Documents", ".json": "Documents", ".pptx": "Documents", ".nk": "Compositing", ".gizmo": "Compositing", ".exe": "Programs", ".msi": "Programs"}folders_list = [f for f in SOURCE_FILE.iterdir() if f.is_dir() and f != DATA_DIR]files_list = [f for f in SOURCE_FILE.iterdir() if f.is_file()]for f in files_list: output_dir = DATA_DIR / dirs.get(f.suffix, "Autres") output_dir.mkdir(exist_ok=True) f.rename(output_dir / f.name)for d in folders_list: output_dir = DATA_DIR / "FOLDERS" output_dir.mkdir(exist_ok=True) d.rename(output_dir / d.name)La liste de courses avec sauvegarde dans un fichier
Le même programme que ‘La liste de courses’ précédemment mais augmenté avec la gestion de fichier JSON
import sysimport jsonimport oscur_dir = os.path.dirname(__file__)chemin = cur_dir+r"\liste_de_courses.json"if os.path.exists(chemin): with open(chemin,"r") as f: liste_de_course = json.load(f) passelse: liste_de_course=[]actions = [ "Ajouter un élément à la liste de courses", "Retirer un élément de la liste de courses", "Afficher les éléments de la liste de courses", "Vider la liste de courses", "Quitter le programme"]choix = 0article=""while choix !=5 : print("Choisissez parmi les 5 options suivantes :") for i, element in enumerate(actions): print(f"{i+1} : {element}") reponse = input("Votre choix : ") if reponse.isdigit() : choix = int(reponse) else : print("Vous devez taper un chiffre !\n") continue if choix == 1 : article = input("Que souhaitez-vous ajouter à la liste ? ") liste_de_course.append(article) print(f"L'article '{article}' a bien été ajouté à la liste.\n") elif choix == 2 : article = input("Quel article souhaitez-vous retirer ? ") if article in liste_de_course : liste_de_course.remove(article) print(f"L'article '{article}' a bien été retiré de la liste.\n") else : print(f"L'article '{article}' n'est pas dans la liste.\n") elif choix == 3 : print("Voici le contenu de la liste :\n") for i, element in enumerate(liste_de_course): print(f"{i+1}. {element}") print("__________________________________________\n") elif choix == 4 : liste_de_course.clear() print("La liste de courses a été vidée.\n") else : if choix != 5: print("Je n'ai pas compris. Veuillez recommencez.\n")with open(chemin, "w") as f: json.dump(liste_de_course, f, ensure_ascii = False, indent = 4) passprint("La liste de courses a été sauvegardée ! ")print("A bientôt !")sys.exitLe jeu de rôle
Une simulation de jeu de rôle style années 80. L’utilisateur se bat contre l’ordi, avec 50 points de vie chacun. A chaque tour, l’utilisateur choisit soit d’attaquer, soit de boire une potion pour récupérer des points de vie. Le premier qui arrive à zéro a perdu.
import random
#Déclaration des constantesuser_lives = 50ennemy_lives = 50user_potions = 3
#Message de bienvenueprint("-"*50+"\n")print("*** Bienvenue dans le jeu de role ! ***")print("-"*50+"\n")
#Bouclewhile user_lives > 0 and ennemy_lives > 0: action = input("Souhaitez-vous attaquer (1) ou utiliser une potion (2) ? ") if not action.isdigit(): print("Vous devez saisir un nombre.") continue elif int(action) > 2: print("Vous devez saisir un nombre entre 1 et 2.") continue else: if int(action) == 1: #Choix de l'attaque ennemy_lost = random.randint(5,11) ennemy_lives-=ennemy_lost print(f"L'ennemi a perdu {ennemy_lost} points de vie et est maintenant à {ennemy_lives} points de vie.") else: #Choix de la potion potion = random.randint(15,51) user_lives+=potion user_potions-=1 print(f"Vous prenez un potion. Vous récupérez {potion} points de vie.") print(f"Il vous reste {user_potions} potions et {user_lives} points de vie.") print("Vous passez votre tour...") #Dans tous les cas, l'ennemi attaque user_lost=random.randint(5,16) user_lives-=user_lost print(f"L'ennemi vous attaque. Vous perdez {user_lost} points de vie.\nVous avez maintenant {user_lives} points de vie.")#L'un des deux joueurs a perdu#On teste qui a perduif user_lives <= 0: print("\nVous avez perdu !")elif ennemy_lives <= 0: print("\nVous avez gagné !")Le nombre mystère
Un programme simple, à exécuter dans un terminal, qui implémente le jeu du nombre mystère. Un nombre est choisi aléatoirement, entre 0 et 100, et l’utilisateur à 5 essais pour trouver le nombre choisi.
import randomimport sysessais = 5nombre_mystere = random.randint(0,101)nombre_propose = 0print("-"*50)print("*** Le jeu du nombre mystère ***")print("Tu dois trouver un nombre entre 0 et 100.")print("-"*50)while essais > 0: print(f"Il te reste {essais} essais") nombre_propose = input("Devine le nombre : ") if not nombre_propose.isdigit(): print("Il faut entrer un nombre valide.") continue else: nombre_propose=int(nombre_propose) if nombre_propose == nombre_mystere: print(f"Bravo ! Tu as gagné en {5-essais} essais ! Le nombre mystère est bien {nombre_mystere}.") print("Le jeu est terminé.") sys.exit() else: if nombre_propose < nombre_mystere: print(f"Le nombre mystère est plus grand que {nombre_propose}") else: print(f"Le nombre mystère est plus petit que {nombre_propose}") essais -= 1 continueprint("-"*50)print(f"Tu as perdu ! Le nombre mystère était {nombre_mystere}.")La liste de courses
Un petit programme, à exécuter dans un terminal, qui permet de simuler la gestion d’une liste de courses.
On peut ajouter un article, le retirer, afficher la liste ou vider la liste.
import sysactions = ["Ajouter un élément à la liste de courses","Retirer un élément de la liste de courses","Afficher les éléments de la liste de courses","Vider la liste de courses","Quitter le programme"]choix = 0liste_de_course=[]article=""while choix !=5 :print("Choisissez parmi les 5 options suivantes :")for i, element in enumerate(actions):print(f"{i+1} : {element}")reponse = input("Votre choix : ")if reponse.isdigit() :choix = int(reponse)else :print("Vous devez taper un chiffre !\n")continueif choix == 1 :article = input("Que souhaitez-vous ajouter à la liste ? ")liste_de_course.append(article)print(f"L'article '{article}' a bien été ajouté à la liste.\n")elif choix == 2 :article = input("Quel article souhaitez-vous retirer ? ")if article in liste_de_course :liste_de_course.remove(article)print(f"L'article '{article}' a bien été retiré de la liste.\n")else :print(f"L'article '{article}' n'est pas dans la liste.\n")elif choix == 3 :print("Voici le contenu de la liste :\n")for i, element in enumerate(liste_de_course):print(f"{i+1}. {element}")print("-"*50+"\n")elif choix == 4 :liste_de_course.clearprint("La liste de courses a été vidée.\n")else :if choix != 5:print("Je n'ai pas compris. Veuillez recommencez.\n")print("A bientôt !")sys.exit
Nicolas MARIE © 2025
A bientôt ! 😉



