Python項目中正確讀取寫入配置的方式
1、將配置寫在Python文件中
這種方法非常簡單,但它存在嚴重的安全問題,我們都知道不應該把配置寫在代碼中,如果有人把我們的源代碼上傳到了github中,那么數據庫的配置就相當于向全世界公開了,當然,當配置文件不包含敏感信息時,也可以才有這種簡單的方法。
2、利用外部配置文件
讓配置文件和代碼獨立開來,通常使用 json、yaml或者ini的文件格式來存儲配置。
結合環境變量和 python 庫讀取外部文件,首先開發通常不會接觸到生成環境,因此生成環境的配置文件由運維來寫,運維將應用所需要的配置寫好后,放到生產服務器的指定位置,代碼從指定位置讀取配置。
為了方便程序的統一調試,可以提前約定好一個系統環境變量(XXX_CONFIG_PATH)來指定配置文件的存放路徑。
例如:export XXX_CONFIG_PATH =
/home/test/configs/config.ini 此為設置臨時環境變量
linux、ubuntu 環境變量
查看環境變量:
env
設置永久環境變量
1.在/etc/profile 的文件下編輯,所改變的環境變量是面向所有用戶的
export CLASSPATH = /../... 該路徑為絕對路徑
2.在當前用戶目錄下./barsh_profile文件中修改 進行修改的話,僅對當前的用戶生效
vim /home/wens/.barshc
export CLASSPATH = /../... 該路徑為絕對路徑
最后使用source命令 可以直接使環境變量生效
source /home/wens/.barshc //直接跟環境變量的文件
windows 環境變量
查看環境變量:
set
查看某個環境變量:
set path
修改環境變量
輸入 “set 變量名=變量內容”即可。比如將path設置為“d:\nmake.exe”,只要輸入set path="d:\nmake.exe"
注意:所有的在cmd命令行下對環境變量的修改只對當前窗口有效,不是永久性的修改。也就是說當關閉此cmd命令行窗口后,將不再起作用。
永久性修改環境變量的方法有兩種:
一種是直接修改注冊表
另一種是通過我的電腦-〉屬性-〉高級,來設置系統的環境變量(查看詳細)
設置了環境變量后,需要重啟 pycharm 生效
3、直接使用系統環境變量讀取配置
此方法不使用文件來存儲配置信息,將所有的配置信息存儲到環境變量中,在實踐中比較常見,運維通過 ansible 部署腳本,在程序運行前將需要配置的信息導入到環境變量中。
不利用文件存儲,在一定程度上加強了對密碼等配置信息的保護,但也增加了運維的工作量,尤其是當需要修改配置時。
4、微服務架構
在一些微服務架構中,會專門開發配置中心,程序直接從線上讀取配置,配置的管理也會開發一套GUI,方便開發和運維。
5、一般項目中建議的配置方式
-app
-__init.py
-app.py
-settings
-__init__.py
-base.py
-dev.py
-prod.py
其中 __init__.py 中,添加判斷邏輯,判斷當前環境使用 開發環境還是生產環境,從而加載不同的配置參數。
# settings/__init__.py
import os
# os.environ.get() 用于獲取系統中的環境變量,因為在生產環境中,一般都會把一些關鍵性的參數寫到系統的環境中。
# 所以PROFILE的值其實就是我們配置的環境變量的值。如果沒有配這個值,默認走dev的配置。
# PYTHON_PRO_PROFILE = os.environ.get("PYTHON_PRO_PROFILE", "dev")
PYTHON_PRO_PROFILE = os.environ.get("PYTHON_PRO_PROFILE")
print("是開發環境還是生產環境: ", PYTHON_PRO_PROFILE)
if PYTHON_PRO_PROFILE == "dev":
from .dev import *
elif PYTHON_PRO_PROFILE == "prod":
from .prod import *
else:
raise Exception("Not supported runtime profile {}".format(PYTHON_PRO_PROFILE))
其中 base.py 存儲一些公用的配置,然后在開發環境 dev.py 與生產環境 prod.py 中導入 base.py 的變量。
# settings/base.py
import os
import time
# os.path.abspath: 獲取完整路徑(包含文件名)
current_exec_abspath = os.path.abspath(__file__)
current_exec_dir_name, _ = os.path.split(current_exec_abspath)
current_up_dir, _ = os.path.split(current_exec_dir_name)
current_up2_dir, _ = os.path.split(current_up_dir)
print('------log dir=------', current_up2_dir)
# 日志文件路徑設置
log_path = f"{current_up2_dir}/logs"
if not os.path.exists(log_path):
os.makedirs(log_path)
t = time.strftime("%Y_%m_%d")
log_path_file = f"{log_path}/interface_log_{t}.log"
其中 dev.py:
# 導入了base下所有參數
from .base import *
database = {
"protocol": "mysql+mysqlconnector",
"username": "xxxxxx",
"password": "hash string",
"port": 3306,
"database": "repo"
}
其中 prod.py:
# 導入了base下所有參數
from .base import *
database = {
"protocol": "xxxxxxxxxxx",
"username": "xxxxxxxxxxx",
"password": "xxxxxxxxxxx",
"port": 3344,
"database": "xxxx"
}
對于一些敏感信息可在環境變量里設置,通過如下方法獲取,例如:
MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp.163.com')
MAIL_USERNAME = os.environ.get('MAIL_USERNAME') or 'test'
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') or '12345678'