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.