Fichiers de configuration Python

Configurations. Tous les stockent de différentes manières. Quelqu'un en .yaml , quelqu'un en .ini et quelqu'un dans le code source, pensant que le "Chemin Django" avec son settings.py vraiment bon.


Dans cet article, je veux essayer de trouver le moyen idéal (le plus probable) de stocker et d'utiliser des fichiers de configuration en Python. Eh bien, partagez aussi votre bibliothèque pour eux :)


Tentative numéro 1


Qu'en est-il du stockage de la configuration dans le code? Eh bien, c'est pratique, et vous n'avez pas besoin d'apprendre de nouvelles langues. Il existe de nombreux projets dans lesquels cette méthode est utilisée, et je tiens à dire, avec beaucoup de succès.


Une configuration typique dans ce style ressemble à ceci:


 # settings.py TWITTER_USERNAME="johndoe" TWITTER_PASSWORD="johndoespassword" TWITTER_TOKEN="......." 

Ça a l'air bien. Une seule chose inquiète, pourquoi les données de sécurité sont-elles stockées dans du code? Comment allons-nous commettre cela? L'énigme. Sauf pour .gitignore notre fichier dans .gitignore , mais ce n'est bien sûr pas une solution du tout.


Quoi qu'il en soit, pourquoi au moins certaines données sont stockées dans le code? Comme le code me semble, c'est aussi un code qui doit exécuter une sorte de logique , et non stocker des données.


Cette approche est en fait beaucoup utilisée où. Dans le même Django. Tout le monde pense que puisque c'est le framework le plus populaire utilisé sur Instagram, ils ne conseilleront rien de mal. Il est dommage que ce ne soit pas le cas.


Un peu plus à ce sujet .


Tentative numéro 2


Eh bien, puisque nous avons décidé que le stockage de données dans le code n'est pas cool, cherchons une alternative. Un nombre considérable de formats différents ont été inventés pour les fichiers de configuration, toml grande popularité.


Mais nous allons commencer par ce que Python lui-même nous offre - .ini . La bibliothèque standard possède une bibliothèque configparser .


Notre config, que nous avons déjà écrit plus tôt:


 # settings.ini [Twitter] username="johndoe" password="johndoespassword" token="....." 

Maintenant, lisez en Python:


 import configparser #   config = configparser.ConfigParser() #    config.read("settings.ini") #   print(config["Twitter"]["username"]) #     ! # 'johndoe' 

Tous les problèmes sont résolus. Les données ne sont pas stockées dans le code, l'accès est facile. Mais ... et si nous avons besoin de lire d'autres configs, bien là json ou yaml par exemple, ou tout d'un coup. Bien sûr, il y a json dans la bibliothèque standard et pyyaml , mais vous devez écrire un tas de code (enfin, ou pas vraiment) pour cela.


La documentation


Tentative numéro 3


Et maintenant, je voudrais vous montrer ma bibliothèque, qui est conçue pour résoudre tous ces problèmes (enfin, ou du moins réduire vos souffrances :)).


Il s'appelle betterconf et est disponible sur PyPi.


L'installation est aussi simple que n'importe quelle autre bibliothèque:


 pip install betterconf 

Initialement, notre configuration est présentée comme une classe avec des champs:


 # settings.py from betterconf import Config, field class TwitterConfig(Config): #  ,    `Config` username = field("TWITTER_USERNAME", default="johndoe") #   `username`,    ,   password = field("TWITTER_PASSWORD", default="johndoespassword") #  token = field("TWITTER_TOKEN", default=lambda: raise RuntimeError("Account's token must be defined!") #   ,      cfg = TwitterConfig() print(cfg.username) # 'johndoe' 

Par défaut, la bibliothèque essaie de prendre des valeurs des variables d'environnement, mais nous pouvons également configurer ceci:


 from betterconf import Config, field from betterconf.config import AbstractProvider import json class JSONProvider(AbstractProvider): #     SETTINGS_JSON_FILE = "settings.json" #      def __init__(self): with open(self.SETTINGS_JSON_FILE, "r") as f: self._settings = json.load(f) #    def get(self, name): return self._settings.get(name) #    -  ,  - None.     ,   None. provider = JSONProvider() class TwitterConfig(Config): username = field("twitter_username", provider=provider) #      # ... cfg = TwitterConfig() # ... 

De cet exemple, il s'ensuit que nous pouvons utiliser différents fournisseurs pour recevoir des données. Et c'est vraiment parfois pratique, dis-je par expérience personnelle.


Et si nous avons des valeurs booléennes ou des nombres dans les configurations, ils finiront par arriver en chaînes de toute façon. Et pour cela, il existe une solution:


 from betterconf import Config, field #     2  from betterconf.caster import to_bool, to_int class TwitterConfig(Config): # ... post_tweets = field("TWITTER_POST_TWEETS", caster=to_bool) # ... 

Ainsi, toutes les valeurs similaires aux types booléens (à savoir true et false seront converties en un booléen Python. La casse n'est pas sensible à la casse.


Écrire votre lanceur de sorts est également simple:


 from betterconf.caster import AbstractCaster class DashToDotCaster(AbstractCaster): def cast(self, val): return val.replace("-", ".") #     to_dot = DashToDotCaster() # ... 

Dépôt Github avec une documentation plus détaillée .


Résumé


Ainsi, nous sommes arrivés à la conclusion que le stockage des paramètres dans le code source n'est pas bon. Pour cela, différents formats ont déjà été inventés. Eh bien, et vous avez rencontré une autre bibliothèque utile (comme je pense :)).


PS


Oui, vous pouvez également inclure Pydantic , mais je pense qu'il est trop léger pour de telles tâches.

Source: https://habr.com/ru/post/fr485236/


All Articles