0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python程序配置文件管理的最佳工程實(shí)踐

馬哥Linux運(yùn)維 ? 來(lái)源:馬哥Linux運(yùn)維 ? 2023-05-04 10:00 ? 次閱讀

背景

最近在結(jié)合 Python-3.12.0a6 版本開(kāi)發(fā)一個(gè)多線程架構(gòu)的后臺(tái)服務(wù);服務(wù)啟動(dòng)時(shí)會(huì)讀取配置文件,并且要求所有線程共享同一份配置。

服務(wù)本身直接通過(guò) http 接口來(lái)動(dòng)態(tài)調(diào)整配置項(xiàng)的值,還要做到服務(wù)退出之后持久化配置項(xiàng)到配置文件。

一開(kāi)始以為這個(gè)用 Python 寫(xiě)也會(huì)要用幾百行,最后發(fā)現(xiàn)完成核心功能就只需要不到 50 行,Python 牛逼?。?!


需求一:支持簡(jiǎn)單的配置項(xiàng)

假設(shè)我們目前只支持 name 和 port 兩個(gè)配置項(xiàng),多支持幾個(gè)不難,只是不方便演示。

"""實(shí)例配置管理
"""


from dataclasses import dataclass




@dataclass
class Config(object):
    name:str= "mysql"
    port:int = 3306

看起來(lái)是沒(méi)問(wèn)題了,下面可以試用一下,也順帶引導(dǎo)出第二個(gè)需求。

In [6]: a = Config()


In [7]: b = Config()


In [8]: id(a)
Out[8]: 4407850896


In [9]: id(b)
Out[9]: 4407852496

可以看到兩個(gè)配置對(duì)象的 ID 值不一樣。由于配置文件只有一個(gè),我們希望配置對(duì)象也只有一個(gè)。


需求二:配置對(duì)象全局唯一

交代一個(gè)背景,解釋器在做 import 的時(shí)候是單一線程在跑的。有了這個(gè)前提我們可以少寫(xiě)一些加鎖的代碼,能少寫(xiě)一行算一行吧。

"""實(shí)例配置管理
"""


from dataclasses import dataclass




@dataclass
class Config(object):
    name:str= "mysql"
    port:int = 3306


    _instance = None


    # 單例模式
    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

用 Python 就是這么的簡(jiǎn)單,幾行代碼就搞定了。但是還是要測(cè)試一下順帶引導(dǎo)出下一個(gè)需求。

In [4]: a = Config()


In [5]: b = Config()


In [6]: id(a)
Out[6]: 4414751568


In [7]: id(b)
Out[7]: 4414751568

現(xiàn)在配置對(duì)象已經(jīng)是單例了,但還有一個(gè)問(wèn)題,它的每個(gè)配置項(xiàng)的值都是默認(rèn)值,我們當(dāng)然是希望它在創(chuàng)建對(duì)象的時(shí)候是使用配置文件中的值啦。下面看需求三怎么實(shí)現(xiàn)。


需求三:根據(jù)配置文件構(gòu)造配置對(duì)象

假設(shè)我們的配置文件被 “持久化” 到了 /tmp/config.json ,現(xiàn)在就可以寫(xiě)讀取配置文件并更新配置對(duì)象值的代碼了。

"""實(shí)例配置管理
"""


import json
import logging
from pathlib import Path
from dataclasses import dataclass




@dataclass
class Config(object):
    name:str= "mysql"
    port:int = 3306


    _instance = None


    # 單例模式
    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance


    # 讀取配置文件
    def __post_init__(self):
        """如果配置文件存在就用配置文件中的值,覆蓋默認(rèn)值。在這個(gè)過(guò)程中如果遇到異常就保持默認(rèn)值
        """
        if (config_file:=Path("/tmp/config.json")) and config_file.exists():
            try:
                with open(config_file) as f:
                    json_data = json.loads(f.read())
                    self.__dict__.update(json_data)
            except Exception as err:
                pass
        else:
            logging.warn("config file '{}' not exists. well using defautl values .".format(config_file))

假設(shè)我們的配置文件內(nèi)容是這樣的。

cat /tmp/config.json 
{
  "name": "trump",
  "port": 8848
}

下面的測(cè)試一下

In [2]: a = Config()


In [3]: a
Out[3]: Config(name='trump', port=8848)


In [4]: b = Config()


In [5]: b
Out[5]: Config(name='trump', port=8848)


In [6]: a == b
Out[6]: True

可以看到 name 和 port 已經(jīng)沒(méi)有使用默認(rèn)的 "mysql" 和 3306 了,而是使用了配置文件中的值。

到這里我們只剩下最后一個(gè)需求,就是在程序退出的時(shí)候,把配置對(duì)象的值更新回配置文件。這個(gè)就看需求四怎么寫(xiě)。


需求四:程序退出前自動(dòng)持久化配置對(duì)象到配置文件

解釋器在退出前有個(gè)鉤子(atexit),我們可以在這里指定回調(diào)函數(shù),這個(gè)時(shí)候保存配置文件再適合不過(guò)。

"""實(shí)例配置管理
"""


import json
import atexit
import logging
from pathlib import Path
from dataclasses import dataclass, asdict




@dataclass
class Config(object):
    name:str= "mysql"
    port:int = 3306


    _instance = None


    # 單例模式
    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance


    # 讀取配置文件
    def __post_init__(self):
        """如果配置文件存在就用配置文件中的值,覆蓋默認(rèn)值;在這個(gè)過(guò)程中如果遇到異常就保持默認(rèn)值。程序退出時(shí)持久到到配置到文件。
        """
        if (config_file:=Path("/tmp/config.json")) and config_file.exists():
            try:
                with open(config_file) as f:
                    json_data = json.loads(f.read())
                    self.__dict__.update(json_data)
            except Exception as err:
                pass
        else:
            logging.warn("config file '{}' not exists. well using defautl values .".format(config_file))


        # 程序退出時(shí)保存配置到配置文件 /tmp/config.json
        def sync_to_disk():
"""
            """
            json_str = json.dumps(asdict(self), indent=4)
            with open(config_file, 'w') as f:
                logging.warning("save configs to '{}' ".format(config_file))
                f.write(json_str) 


        atexit.register(sync_to_disk)

驗(yàn)證一下

In [1]: from appconfig import Config


In [2]: a = Config()


In [3]: a.name
Out[3]: 'trump'


In [4]: a.name = "hello-world"


In [5]: exit()
WARNINGsave configs to '/tmp/config.json' 

看日志是已經(jīng)把配置項(xiàng)更新回配置文件了,但是還是 cat 確認(rèn)一下為好。

cat /tmp/config.json 
{
    "name": "hello-world",
    "port": 8848
}

可以看到確實(shí)已經(jīng)把配置項(xiàng)的值更新到文件了。


審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 程序
    +關(guān)注

    關(guān)注

    115

    文章

    3749

    瀏覽量

    80672
  • 配置
    +關(guān)注

    關(guān)注

    1

    文章

    187

    瀏覽量

    18323
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4759

    瀏覽量

    84296

原文標(biāo)題:Python 程序配置文件管理的最佳工程實(shí)踐

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于libconfig進(jìn)行配置文件解析

    本文介紹基于libconfig進(jìn)行配置文件解析
    的頭像 發(fā)表于 06-08 10:18 ?1291次閱讀
    基于libconfig進(jìn)行<b class='flag-5'>配置文件</b>解析

    探討PROE的配置文件——系統(tǒng)配置文件config.pro

    PROE的配置文件讓不少初學(xué)者感到煩惱,盡管不少教材里都會(huì)提到關(guān)于PROE的配置文件。但大多數(shù)顯得過(guò)于理論化,而不便于初學(xué)者理解,可操作性不強(qiáng)。本文力求以通俗的語(yǔ)言結(jié)合
    發(fā)表于 09-28 15:50 ?0次下載

    ICD配置文件的詳細(xì)介紹和配置內(nèi)容的詳細(xì)概述

    配置文件配置文件是利用SCL語(yǔ)言描述變電站設(shè)備對(duì)象模型后生成的文件,用于在不同廠商的配置工具之間交換配置信息。
    的頭像 發(fā)表于 06-02 11:16 ?1.8w次閱讀
    ICD<b class='flag-5'>配置文件</b>的詳細(xì)介紹和<b class='flag-5'>配置</b>內(nèi)容的詳細(xì)概述

    Python進(jìn)行配置文件的教程免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Python進(jìn)行配置文件的教程免費(fèi)下載。
    發(fā)表于 09-30 16:41 ?6次下載
    <b class='flag-5'>Python</b>進(jìn)行<b class='flag-5'>配置文件</b>的教程免費(fèi)下載

    AD8283評(píng)估板設(shè)計(jì)和配置文件

    AD8283評(píng)估板設(shè)計(jì)和配置文件
    發(fā)表于 05-31 16:04 ?9次下載
    AD8283評(píng)估板設(shè)計(jì)和<b class='flag-5'>配置文件</b>

    Python 中常見(jiàn)的配置文件寫(xiě)法有哪些

    固定文件我們可以直接寫(xiě)成一個(gè)? .py ?文件,例如? settings.py ?或? config.py ,這樣的好處就是能夠在同一工程下直接通過(guò)? import ?來(lái)導(dǎo)入當(dāng)中的部分;但如果我們需要在其他 非
    的頭像 發(fā)表于 10-20 16:11 ?2244次閱讀
    <b class='flag-5'>Python</b> 中常見(jiàn)的<b class='flag-5'>配置文件</b>寫(xiě)法有哪些

    labview讀寫(xiě)配置文件實(shí)例分享

    labview讀寫(xiě)配置文件實(shí)例分享
    發(fā)表于 11-01 16:05 ?45次下載

    SpringBoot配置文件application

    Map配置 YML配置文件: sys-num: mymap: "{'a':'aaa','b':'bbb'}" 方法內(nèi): public class learnMap { @Value
    的頭像 發(fā)表于 01-13 15:28 ?591次閱讀

    KT142C語(yǔ)音芯片配置文件總是不起作用?配置文件的問(wèn)題集中歸納

    KT142C語(yǔ)音芯片配置文件總是不起作用?配置文件的問(wèn)題集中歸納
    的頭像 發(fā)表于 10-20 15:04 ?494次閱讀
    KT142C語(yǔ)音芯片<b class='flag-5'>配置文件</b>總是不起作用?<b class='flag-5'>配置文件</b>的問(wèn)題集中歸納

    linux修改網(wǎng)卡ip配置文件

    Linux是一種開(kāi)源的操作系統(tǒng),因此,它給用戶提供了很高的自由度,可以根據(jù)個(gè)人需要進(jìn)行各種定制和配置。其中,修改網(wǎng)絡(luò)接口配置文件是常見(jiàn)的操作,可以通過(guò)修改網(wǎng)卡ip配置文件來(lái)設(shè)置網(wǎng)絡(luò)接口的IP地址
    的頭像 發(fā)表于 11-17 10:51 ?2003次閱讀

    springboot的全局配置文件有幾種

    Spring Boot是一種快速開(kāi)發(fā)框架,其通過(guò)提供配置文件來(lái)實(shí)現(xiàn)對(duì)應(yīng)用程序配置。全局配置文件在Spring Boot中起著非常重要的作用,可以用于
    的頭像 發(fā)表于 12-03 15:28 ?1450次閱讀

    springboot的核心配置文件有哪些

    的工作量。 Spring Boot的核心配置文件主要有以下幾個(gè): application.properties:Spring Boot應(yīng)用程序的主要配置文件。它使用Java的鍵值對(duì)格式來(lái)定義各種
    的頭像 發(fā)表于 12-03 15:30 ?1084次閱讀

    zookeeper的核心配置文件是什么

    ,Zookeeper被廣泛應(yīng)用于服務(wù)發(fā)現(xiàn)、分布式鎖、配置管理等場(chǎng)景中。在Zookeeper的設(shè)計(jì)中,核心配置文件是zoo
    的頭像 發(fā)表于 12-04 10:33 ?653次閱讀

    php的配置文件是什么

    PHP的配置文件是一種用于配置PHP解釋器的文本文件。它包含了一系列的指令和選項(xiàng),用于影響PHP的行為和性能。通過(guò)修改配置文件,可以改變PHP解釋器的默認(rèn)行為,從而滿足不同的需求。 在
    的頭像 發(fā)表于 12-04 15:55 ?1416次閱讀

    oracle配置文件tnsnames怎么配置

    Oracle配置文件tnsnames.ora是一個(gè)文本文件,用于定義數(shù)據(jù)庫(kù)連接的別名和連接信息。通過(guò)配置文件,可以在應(yīng)用程序中使用別名來(lái)連
    的頭像 發(fā)表于 12-06 10:15 ?6597次閱讀