ملفات التكوين بيثون

التكوينات. جميع تخزينها بطرق مختلفة. شخص ما في .yaml ، شخص ما في .ini ، وشخص ما في الكود المصدري ، معتقدًا أن "مسار Django" مع settings.py جيد حقًا.


في هذه المقالة ، أريد أن أحاول إيجاد الطريقة المثالية (على الأرجح) لتخزين واستخدام ملفات التكوين في Python. حسنًا ، شارك أيضًا مكتبتك لهم :)


محاولة رقم 1


ماذا عن تخزين التكوين في التعليمات البرمجية؟ حسنًا ، هذا نوع مناسب ، ولا يلزمك تعلم لغات جديدة. هناك العديد من المشاريع التي تستخدم فيها هذه الطريقة ، وأود أن أقول ، بنجاح كبير.


يبدو التكوين النموذجي في هذا النمط كما يلي:


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

انها تبدو جيدة. قلق واحد فقط ، لماذا يتم تخزين بيانات الأمان في التعليمات البرمجية؟ كيف سنلتزم بذلك؟ اللغز. باستثناء .gitignore في .gitignore ، لكن هذا ، بالطبع ، ليس حلاً على الإطلاق.


على أي حال ، لماذا يتم تخزين بعض البيانات على الأقل في الكود؟ كما يبدو لي رمز ، هو أيضا رمز يجب أن تنفذ نوعا من المنطق ، وليس تخزين البيانات.


يستخدم هذا النهج في الواقع الكثير حيث. في نفس جانغو. يعتقد الجميع أنه نظرًا لأن هذا هو الإطار الأكثر شعبية الذي يتم استخدامه على Instagram نفسه ، فلن ينصحوا بأي شيء سيء. إنه لأمر مؤسف أن هذا ليس كذلك.


أكثر قليلا عن هذا .


محاولة رقم 2


حسنًا ، نظرًا لأننا قررنا أن تخزين البيانات في التعليمات البرمجية ليس رائعًا ، فلنبحث عن بديل. تم اختراع عدد كبير من التنسيقات المختلفة لملفات التكوين ، toml شعبية كبيرة toml .


لكننا سنبدأ بما تقدمه لنا بيثون - .ini . تحتوي المكتبة القياسية على مكتبة configparser .


التكوين لدينا ، والذي كتبنا بالفعل في وقت سابق:


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

اقرأ الآن في بيثون:


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

يتم حل جميع المشاكل. لا يتم تخزين البيانات في رمز ؛ الوصول سهل. ولكن ... وإذا كنا بحاجة إلى قراءة التكوينات الأخرى ، فهناك أيضًا json أو yaml على سبيل المثال ، أو جميعها مرة واحدة. بالطبع ، هناك json في المكتبة القياسية و pyyaml ، ولكن عليك أن تكتب مجموعة من التعليمات البرمجية (جيدًا أم لا) حقًا لهذا الغرض.


وثائق .


محاولة رقم 3


والآن ، أود أن أوضح لك مكتبتي ، المصممة لحل جميع هذه المشكلات (جيدًا ، أو على الأقل تقليل معاناتك :)).


ويسمى betterconf ومتاح على PyPi.


التثبيت بسيط مثل أي مكتبة أخرى:


 pip install betterconf 

في البداية ، يتم تقديم التكوين الخاص بنا كصف مع حقول:


 # 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' 

بشكل افتراضي ، تحاول المكتبة أخذ قيم من متغيرات البيئة ، ولكن يمكننا أيضًا تكوين هذا:


 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() # ... 

من هذا المثال ، يتبع أنه يمكننا استخدام مختلف مقدمي الخدمات لتلقي البيانات. وأنا حقا مريحة في بعض الأحيان ، وأنا أقول من تجربة شخصية.


حسنًا ، ماذا لو كان لدينا قيم أو أرقام منطقية في التكوينات ، فسوف تأتي في النهاية سلاسل على أي حال. ولهذا هناك حل:


 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) # ... 

وبالتالي ، سيتم تحويل جميع القيم المشابهة لأنواع Boolean (وهي true false إلى bool بيثون). الحالة ليست حساسة لحالة الأحرف.


من السهل أيضًا كتابة العجلات الخاصة بك:


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

مستودع جيثب مع وثائق أكثر تفصيلا .


النتائج


وهكذا ، توصلنا إلى استنتاج مفاده أن تخزين الإعدادات في الكود المصدري ليس جيدًا. لهذا ، تم اختراع أشكال مختلفة بالفعل. حسنًا ، وقد قابلت مكتبة أخرى مفيدة (كما أعتقد :)).


PS


نعم ، يمكنك أيضًا تضمين Pydantic ، لكنني أعتقد أنها خفيفة الوزن جدًا لمثل هذه المهام.

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


All Articles