1# Paramètres et variables d'environnement { #settings-and-environment-variables }23Dans de nombreux cas, votre application peut avoir besoin de paramètres ou de configurations externes, par exemple des clés secrètes, des identifiants de base de données, des identifiants pour des services d'e-mail, etc.45La plupart de ces paramètres sont variables (peuvent changer), comme les URL de base de données. Et beaucoup peuvent être sensibles, comme les secrets.67C'est pourquoi il est courant de les fournir via des variables d'environnement lues par l'application.89Une **variable d'environnement** (aussi appelée **env var**) est une valeur qui vit en dehors du code Python, dans le système d'exploitation, et qui peut être lue par votre application et d'autres programmes.1011Vous pouvez créer une variable d'environnement pour une commande lorsque vous l'exécutez. Vous verrez les commandes spécifiques à chaque plateforme ci-dessous.1213/// tip | Astuce1415Lisez le [guide des variables d'environnement](https://tiangolo.com/guides/environment-variables/) pour une explication détaillée du fonctionnement des variables d'environnement.1617///1819## Types et validation { #types-and-validation }2021Ces variables d'environnement ne gèrent que des chaînes de texte, car elles sont externes à Python et doivent être compatibles avec d'autres programmes et le reste du système (et même avec différents systèmes d'exploitation, comme Linux, Windows et macOS).2223Cela signifie que toute valeur lue en Python depuis une variable d'environnement sera une `str`, et toute conversion vers un autre type ou toute validation doit être effectuée dans le code.2425## Pydantic `Settings` { #pydantic-settings }2627Heureusement, Pydantic fournit un excellent utilitaire pour gérer ces paramètres provenant des variables d'environnement avec [Pydantic : gestion des paramètres](https://pydantic.dev/docs/validation/latest/concepts/pydantic_settings/).2829### Installer `pydantic-settings` { #install-pydantic-settings }3031Ajoutez le paquet `pydantic-settings` à votre projet :3233<div class="termy">3435```console36$ uv add pydantic-settings37---> 100%38```3940</div>4142Il est aussi inclus lorsque vous installez les extras `all` avec :4344<div class="termy">4546```console47$ uv add "fastapi[all]"48---> 100%49```5051</div>5253### Créer l'objet `Settings` { #create-the-settings-object }5455Importez `BaseSettings` depuis Pydantic et créez une sous-classe, comme pour un modèle Pydantic.5657De la même manière qu'avec les modèles Pydantic, vous déclarez des attributs de classe avec des annotations de type, et éventuellement des valeurs par défaut.5859Vous pouvez utiliser toutes les mêmes fonctionnalités et outils de validation que pour les modèles Pydantic, comme différents types de données et des validations supplémentaires avec `Field()`.6061{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}6263/// tip | Astuce6465Si vous voulez quelque chose à copier-coller rapidement, n'utilisez pas cet exemple, utilisez le dernier ci-dessous.6667///6869Ensuite, lorsque vous créez une instance de cette classe `Settings` (dans ce cas, dans l'objet `settings`), Pydantic lira les variables d'environnement de manière insensible à la casse, donc une variable en majuscules `APP_NAME` sera tout de même lue pour l'attribut `app_name`.7071Il convertira ensuite et validera les données. Ainsi, lorsque vous utilisez cet objet `settings`, vous aurez des données des types que vous avez déclarés (par exemple, `items_per_user` sera un `int`).7273### Utiliser `settings` { #use-the-settings }7475Vous pouvez ensuite utiliser le nouvel objet `settings` dans votre application :7677{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}7879### Exécuter le serveur { #run-the-server }8081Ensuite, vous exécuteriez le serveur en passant les configurations comme variables d'environnement ; par exemple, vous pourriez définir un `ADMIN_EMAIL` et `APP_NAME` avec :8283//// tab | Linux, macOS, Windows Bash8485<div class="termy">8687```console88$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" uv run fastapi run main.py8990<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)91```9293</div>9495////9697//// tab | Windows PowerShell9899<div class="termy">100101```console102$ $Env:ADMIN_EMAIL = "deadpool@example.com"103$ $Env:APP_NAME = "ChimichangApp"104$ uv run fastapi run main.py105106<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)107```108109</div>110111////112113/// tip | Astuce114115Dans Bash, pour définir plusieurs env vars pour une seule commande, séparez-les par un espace et placez-les toutes avant la commande.116117///118119Et alors le paramètre `admin_email` serait défini sur `"deadpool@example.com"`.120121Le `app_name` serait `"ChimichangApp"`.122123Et `items_per_user` conserverait sa valeur par défaut de `50`.124125## Paramètres dans un autre module { #settings-in-another-module }126127Vous pouvez placer ces paramètres dans un autre fichier de module comme vous l'avez vu dans [Applications plus grandes - Plusieurs fichiers](../tutorial/bigger-applications.md).128129Par exemple, vous pourriez avoir un fichier `config.py` avec :130131{* ../../docs_src/settings/app01_py310/config.py *}132133Puis l'utiliser dans un fichier `main.py` :134135{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}136137/// tip | Astuce138139Vous aurez également besoin d'un fichier `__init__.py` comme vous l'avez vu dans [Applications plus grandes - Plusieurs fichiers](../tutorial/bigger-applications.md).140141///142143## Paramètres dans une dépendance { #settings-in-a-dependency }144145Dans certains cas, il peut être utile de fournir les paramètres via une dépendance, au lieu d'avoir un objet global `settings` utilisé partout.146147Cela peut être particulièrement utile pendant les tests, car il est très facile de surcharger une dépendance avec vos propres paramètres personnalisés.148149### Le fichier de configuration { #the-config-file }150151En repartant de l'exemple précédent, votre fichier `config.py` pourrait ressembler à :152153{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}154155Notez que maintenant, nous ne créons pas d'instance par défaut `settings = Settings()`.156157### Le fichier principal de l'application { #the-main-app-file }158159Nous créons maintenant une dépendance qui renvoie un nouveau `config.Settings()`.160161{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}162163/// tip | Astuce164165Nous parlerons de `@lru_cache` dans un instant.166167Pour l'instant, vous pouvez supposer que `get_settings()` est une fonction normale.168169///170171Nous pouvons ensuite l'exiger depuis la *fonction de chemin d'accès* comme dépendance et l'utiliser où nous en avons besoin.172173{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}174175### Paramètres et tests { #settings-and-testing }176177Il devient alors très simple de fournir un autre objet de paramètres pendant les tests en créant une surcharge de dépendance pour `get_settings` :178179{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}180181Dans la surcharge de dépendance, nous définissons une nouvelle valeur pour `admin_email` lors de la création du nouvel objet `Settings`, puis nous renvoyons ce nouvel objet.182183Nous pouvons ensuite tester qu'il est bien utilisé.184185## Lire un fichier `.env` { #reading-a-env-file }186187Si vous avez de nombreux paramètres susceptibles de beaucoup changer, peut-être dans différents environnements, il peut être utile de les placer dans un fichier, puis de les lire depuis celui-ci comme s'il s'agissait de variables d'environnement.188189Cette pratique est suffisamment courante pour avoir un nom ; ces variables d'environnement sont fréquemment placées dans un fichier `.env`, et le fichier est appelé un « dotenv ».190191/// tip | Astuce192193Un fichier commençant par un point (`.`) est un fichier caché dans les systèmes de type Unix, comme Linux et macOS.194195Mais un fichier dotenv n'a pas forcément exactement ce nom de fichier.196197///198199Pydantic prend en charge la lecture depuis ce type de fichiers en utilisant une bibliothèque externe. Vous pouvez en lire davantage ici : [Pydantic Settings : prise en charge de Dotenv (.env)](https://pydantic.dev/docs/validation/latest/concepts/pydantic_settings/#dotenv-env-support).200201/// tip | Astuce202203Pour que cela fonctionne, ajoutez `python-dotenv` à votre projet avec `uv add python-dotenv`.204205///206207### Le fichier `.env` { #the-env-file }208209Vous pouvez avoir un fichier `.env` avec :210211```bash212ADMIN_EMAIL="deadpool@example.com"213APP_NAME="ChimichangApp"214```215216### Lire les paramètres depuis `.env` { #read-settings-from-env }217218Puis mettre à jour votre `config.py` avec :219220{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}221222/// tip | Astuce223224L'attribut `model_config` est utilisé uniquement pour la configuration Pydantic. Vous pouvez en lire davantage ici : [Pydantic : Concepts : Configuration](https://pydantic.dev/docs/validation/latest/concepts/config/).225226///227228Ici, nous définissons la configuration `env_file` à l'intérieur de votre classe Pydantic `Settings` et lui attribuons le nom du fichier dotenv que nous voulons utiliser.229230### Créer `Settings` une seule fois avec `lru_cache` { #creating-the-settings-only-once-with-lru-cache }231232Lire un fichier depuis le disque est normalement une opération coûteuse (lente), vous voudrez donc probablement le faire une seule fois puis réutiliser le même objet de paramètres, au lieu de le lire à chaque requête.233234Mais chaque fois que nous faisons :235236```Python237Settings()238```239240un nouvel objet `Settings` serait créé, et à sa création il lirait à nouveau le fichier `.env`.241242Si la fonction de dépendance était simplement :243244```Python245def get_settings():246 return Settings()247```248249nous créerions cet objet pour chaque requête, et nous lirions le fichier `.env` pour chaque requête. ⚠️250251Mais comme nous utilisons le décorateur `@lru_cache` au-dessus, l'objet `Settings` sera créé une seule fois, la première fois qu'il est appelé. ✔️252253{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}254255Ensuite, pour tout appel ultérieur de `get_settings()` dans les dépendances pour les requêtes suivantes, au lieu d'exécuter le code interne de `get_settings()` et de créer un nouvel objet `Settings`, il renverra le même objet que celui retourné au premier appel, encore et encore.256257#### Détails techniques de `lru_cache` { #lru-cache-technical-details }258259`@lru_cache` modifie la fonction qu'il décore pour renvoyer la même valeur que celle qui a été retournée la première fois, au lieu de la recalculer en exécutant le code de la fonction à chaque fois.260261Ainsi, la fonction située en dessous sera exécutée une fois pour chaque combinaison d'arguments. Ensuite, les valeurs renvoyées par chacune de ces combinaisons d'arguments seront réutilisées à chaque fois que la fonction sera appelée avec exactement la même combinaison d'arguments.262263Par exemple, si vous avez une fonction :264265```Python266@lru_cache267def say_hi(name: str, salutation: str = "Ms."):268 return f"Hello {salutation} {name}"269```270271votre programme pourrait s'exécuter comme ceci :272273```mermaid274sequenceDiagram275276participant code as Code277participant function as say_hi()278participant execute as Execute function279280 rect rgba(0, 255, 0, .1)281 code ->> function: say_hi(name="Camila")282 function ->> execute: execute function code283 execute ->> code: return the result284 end285286 rect rgba(0, 255, 255, .1)287 code ->> function: say_hi(name="Camila")288 function ->> code: return stored result289 end290291 rect rgba(0, 255, 0, .1)292 code ->> function: say_hi(name="Rick")293 function ->> execute: execute function code294 execute ->> code: return the result295 end296297 rect rgba(0, 255, 0, .1)298 code ->> function: say_hi(name="Rick", salutation="Mr.")299 function ->> execute: execute function code300 execute ->> code: return the result301 end302303 rect rgba(0, 255, 255, .1)304 code ->> function: say_hi(name="Rick")305 function ->> code: return stored result306 end307308 rect rgba(0, 255, 255, .1)309 code ->> function: say_hi(name="Camila")310 function ->> code: return stored result311 end312```313314Dans le cas de notre dépendance `get_settings()`, la fonction ne prend même aucun argument, elle renvoie donc toujours la même valeur.315316De cette façon, elle se comporte presque comme s'il s'agissait simplement d'une variable globale. Mais comme elle utilise une fonction de dépendance, nous pouvons alors la surcharger facilement pour les tests.317318`@lru_cache` fait partie de `functools` qui fait partie de la bibliothèque standard de Python, vous pouvez en lire davantage dans la [documentation Python pour `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache).319320## Récapitulatif { #recap }321322Vous pouvez utiliser Pydantic Settings pour gérer les paramètres ou configurations de votre application, avec toute la puissance des modèles Pydantic.323324* En utilisant une dépendance, vous pouvez simplifier les tests.325* Vous pouvez utiliser des fichiers `.env` avec.326* Utiliser `@lru_cache` vous permet d'éviter de relire le fichier dotenv à chaque requête, tout en vous permettant de le surcharger pendant les tests.
Findings
✓ No findings reported for this file.