Python Learning

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 :

Le fichier main.py
 
from lib import *
from PySide6 import QtWidgets, QtCore
from 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 os
import json
import logging
CUR_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)
 
 
Fichier app.py
 
from PySide6 import QtWidgets, QtCore
from 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 False
app = 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 QtWidgets
import currency_converter

class 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 re
import string
from tinydb import TinyDB, where
from pathlib import Path

class 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 os
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = os.path.join(CUR_DIR, "data")
DATABASE = os.path.join(DATA_DIR, "database.db")
 
Ensuite on implémente le module avec la classe Liste() et ses méthodes : lib.py
import json
import logging
import os
import sqlite3
from 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)
 
Et enfin le script principal pour l’execution du programme dans un terminal : main.py
 
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 = False
bdcourses = False
bdtaches = False
 
def 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 True
 
def 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 ! ")
                break
 

La 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 json
import logging
import os
from constants import DATA_DIR
LOGGER = 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 True
if __name__ == "__main__":
    liste = Liste("courses")
    liste.ajouter("Pommes")
    liste.ajouter("Poires")
    liste.afficher()
    liste.sauvegarder()
 
 
Le fichier de constantes : constants.py
 
import os
CUR_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 Path
import os
SOURCE_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))
 
Si vous voulez tester ce script, voici le fichier à utiliser : fichier.txt
 
 

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 Path
SOURCE_FILE =Path(r"C:\Users\***\Downloads") #remplacer *** par le nom utilisateur sur windows
DATA_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 sys
import json
import os
cur_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)
        pass
else:
    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 = 0
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")
        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)
    pass
print("La liste de courses a été sauvegardée ! ")
print("A bientôt !")
sys.exit
 

Le 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 constantes
user_lives = 50
ennemy_lives = 50
user_potions = 3
#Message de bienvenue
print("-"*50+"\n")
print("*** Bienvenue dans le jeu de role ! ***")
print("-"*50+"\n")
#Boucle
while 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 perdu
if 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 random
import sys
essais = 5
nombre_mystere = random.randint(0,101)
nombre_propose = 0
print("-"*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
            continue
print("-"*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 sys

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 = 0

liste_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")

        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("-"*50+"\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")

print("A bientôt !")

sys.exit
Nicolas MARIE © 2025


A bientôt ! 😉