Accueil Blog Embarquez dans le voyage Python
Python

Embarquez dans le voyage Python

Maîtriser les classes, l'abstraction, les packages et Poetry. Un guide pour structurer ses projets Python — de la gestion de version à FastAPI.

Embarquez dans votre voyage Python : maîtriser les classes, l’abstraction, les packages et Poetry pour les développeurs en herbe.

Introduction

Dans ce guide, les développeurs en herbe exploreront les éléments fondamentaux de Python qui sont cruciaux pour construire des applications robustes. De la compréhension des classes et de l’abstraction à l’organisation du code avec des packages et des modules, vous acquerrez des connaissances pratiques pour structurer efficacement vos projets.

Gestion des packages et des dépendances

La gestion des packages Python est le processus de gestion des dépendances et des packages utilisés par les projets Python. Cela inclut l’installation, la mise à niveau et la suppression des packages, ainsi que le suivi de leurs versions, des exigences et la gestion des versions de Python. Outils populaires : Pyenv, Poetry, UV, Conda.

A — Gérer la version de Python avec Pyenv

Pyenv est un outil qui vous permet de gérer plusieurs versions de Python sur votre ordinateur. Il aide à installer et basculer facilement entre différentes versions, permettant aux développeurs de travailler avec divers projets nécessitant des versions Python spécifiques.

Pour installer Pyenv, allez sur le repo Github et suivez les étapes selon votre environnement.

Installation

curl https://pyenv.run | bash

Cela installera pyenv ainsi que quelques plugins utiles : pyenv-virtualenv, pyenv-update, pyenv-doctor, pyenv-which-ext.

Lister et installer

pyenv install --list
pyenv install 3.13.0
pyenv versions
pyenv global 3.13.0
python -V

B — Gérer les dépendances et le packaging avec Poetry

Poetry est un outil Python conçu pour la gestion des dépendances et le packaging.

Installation

curl -sSL https://install.python-poetry.org | python3 -

Utilisation de base

poetry new poetry-demo

Arborescence générée :

poetry-demo
├── README.md
├── poetry_demo
│   └── __init__.py
├── pyproject.toml
└── tests
    └── __init__.py

pyproject.toml :

[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["James Kokou GAGLO <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.10"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Dépendances et environnements virtuels

poetry add playwright
poetry env use python3.12
poetry env list
poetry env info

Poe — plugin Poetry pour la gestion des tâches

pip install poethepoet
[tool.poe.tasks]
py-version = "python --version"
poetry poe py-version

C — Module et package Python

Un module est un fichier unique contenant du code Python. Un package est un répertoire contenant un ou plusieurs modules ainsi qu’un fichier __init__.py. Chaque module a un attribut __name__ ; pour un script lancé directement, __name__ == "__main__".

poetry-demo
├── poetry_demo
│   ├── __init__.py
│   ├── main.py
│   ├── module1.py
│   ├── subpackage1
│   │   ├── __init__.py
│   │   └── module2.py
│   └── subpackage2
│       ├── __init__.py
│       └── module3.py
# main.py
import module1
from subpackage1 import module2
from subpackage2 import module3

print(module1.func1())
print(module2.func2())
print(module3.func3())

D — Concepts Python et POO

Héritage

class Animal:
    def speak(self):
        return "Je fais un son."

class Dog(Animal):
    def speak(self):
        return "Woof!"

dog = Dog()
print(dog.speak())  # "Woof!"

Utilisez super() pour accéder aux méthodes de la classe parente.

Polymorphisme

class Cat:
    def speak(self):
        return "Meow!"

class Dog:
    def speak(self):
        return "Woof!"

animals = [Cat(), Dog()]
for animal in animals:
    print(animal.speak())

Abstraction

from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

Méthodes de classe et méthodes statiques

class MyClass:
    @classmethod
    def from_string(cls, arg):
        return cls(arg)

    @staticmethod
    def is_valid(arg):
        return arg > 0

E — Pydantic : validation des données

Pydantic est une bibliothèque de validation de données utilisant les annotations de type Python pour valider les données d’entrée.

Définir un modèle

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int
    email: str = None

Validation

user_data = {"name": "Alice", "age": 30}
try:
    user = User(**user_data)
    print(user.name, user.age, user.email)
except ValueError as e:
    print(e)

Validateurs personnalisés

from pydantic import BaseModel, validator

class User(BaseModel):
    name: str
    age: int

    @validator('age')
    def check_age(cls, value):
        if value < 0:
            raise ValueError("L'âge doit être positif")
        return value

Sérialisation

user_dict = user.dict()
user_json = user.json()

F — Pydantic Settings : charger paramètres et configurations

from pydantic import BaseSettings, ValidationError

class MyAppSettings(BaseSettings):
    database_url: str
    debug_mode: bool = False
    max_connections: int = 10

    class Config:
        env_file = '.env'
        env_prefix = 'MYAPP_'
import os
os.environ['MYAPP_DATABASE_URL'] = 'sqlite:///mydb.sqlite'
os.environ['MYAPP_DEBUG_MODE'] = 'True'

settings = MyAppSettings()
print(settings.json(indent=2))

G — Click : interface en ligne de commande

import click

@click.command()
@click.option('--name', default='World', help='La personne à saluer.')
def hello(name):
    """Programme simple qui salue NAME."""
    click.echo(f'Hello {name}!')

if __name__ == '__main__':
    hello()
python script.py --name James
python script.py

H — SQLAlchemy : ORM SQL

import datetime, uuid
from loguru import logger
from sqlalchemy import create_engine, func, MetaData
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import DeclarativeBase, mapped_column, Mapped, registry, Session
from typing import Type, TypeVar, Generic

_database = create_engine(settings.db_url, echo=settings.db_debug)
mapper_registry = registry()
my_metadata = MetaData()

T = TypeVar('T', bound='PsqlBaseModel')

class PsqlBaseModel(DeclarativeBase, Generic[T]):
    metadata = my_metadata
    id = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    created_at: Mapped[datetime.datetime] = mapped_column(server_default=func.now())
    updated_at: Mapped[datetime.datetime] = mapped_column(server_default=func.now(), server_onupdate=func.now())

    @staticmethod
    def bulk_insert(objects):
        with Session(_database) as session:
            session.bulk_save_objects(objects)
            session.commit()

    @classmethod
    def get_by_hash(cls: Type[T], hash: str):
        with Session(_database) as session:
            return session.query(cls).filter(cls.hash == hash).first()

Création des tables :

PsqlBaseModel.metadata.create_all(_database)

Modèle Product avec trigger PostgreSQL :

class Product(PsqlBaseModel):
    __tablename__ = "products"
    name: Mapped[str] = mapped_column(nullable=True)
    hash: Mapped[str] = mapped_column(index=True)
    price: Mapped[int] = mapped_column(index=True, type_=DECIMAL(10,2), nullable=True, default=0)
    url: Mapped[str]
    website: Mapped[str]
    image: Mapped[str] = mapped_column(nullable=True)
    website_updated_at: Mapped[datetime.datetime]
    crawler_updated_at: Mapped[datetime.datetime]

I — Alembic : migrations SQLAlchemy

À venir.

J — FastAPI : framework web pour construire des API

À venir.