一日一技:如何正確管理項(xiàng)目的環(huán)境變量
在之前的公眾號(hào)文章:開(kāi)發(fā)經(jīng)驗(yàn):如何正確設(shè)置開(kāi)發(fā)環(huán)境與生產(chǎn)環(huán)境的配置參數(shù)中,我提到了把項(xiàng)目的開(kāi)發(fā)環(huán)境與生產(chǎn)環(huán)境的配置文件分開(kāi)管理這種方式。
實(shí)際上,項(xiàng)目的配置信息,除了用配置文件以外,還可以使用環(huán)境變量來(lái)進(jìn)行設(shè)置。有一些項(xiàng)目,他們不用配置文件設(shè)置敏感信息,因?yàn)楹ε乱徊恍⌒木桶衙舾行畔l(fā)送到了Github上面。而是把所有敏感信息設(shè)置到環(huán)境變量里面。代碼直接從環(huán)境變量讀取這些信息。
在Python里面,讀取環(huán)境變量非常簡(jiǎn)單:
- import os
- value = os.getenv('變量名')
假設(shè)有一個(gè)項(xiàng)目,它運(yùn)行的時(shí)候需要連Redis/MongoDB/Kafka/ElasticSearch。配置信息有五六十條。那么,它可能需要設(shè)置很多的環(huán)境變量,像下面這樣:
- export REDIS_HOST=xxx
- export REDIS_PORT=xxx
- export REDIS_PASSWORD=xxx
- export MONGODB_URI=xxxx
- export KAFKA_SERVER=xxx
- ...
這樣做的好處顯而易見(jiàn),一旦設(shè)置好環(huán)境變量以后,每次啟動(dòng)程序只需要直接運(yùn)行代碼就可以了。當(dāng)你在開(kāi)發(fā)機(jī)上面運(yùn)行,它自動(dòng)就連開(kāi)發(fā)環(huán)境;當(dāng)你在生產(chǎn)環(huán)境來(lái)運(yùn)行,它自動(dòng)就會(huì)連生產(chǎn)環(huán)境。
但壞處也很明顯,如果你有多個(gè)環(huán)境,每次重新修改環(huán)境變量就非常麻煩。一般來(lái)說(shuō),生產(chǎn)環(huán)境只有一個(gè),但你還有開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境、預(yù)發(fā)布環(huán)境…。其中生產(chǎn)環(huán)境的配置參數(shù)你是拿不到的,但另外幾個(gè)環(huán)境的參數(shù)你是可以拿到的。假設(shè)你現(xiàn)在的代碼在開(kāi)發(fā)機(jī)運(yùn)行正常,但是放到測(cè)試環(huán)境就失敗了。那么你想在開(kāi)發(fā)機(jī)使用測(cè)試環(huán)境的參數(shù)來(lái)調(diào)試代碼。這個(gè)時(shí)候你就必須一個(gè)一個(gè)重新設(shè)置環(huán)境變量,這就非常麻煩。
但好在Python已經(jīng)有一個(gè)用來(lái)管理項(xiàng)目環(huán)境變量的第三方庫(kù)python-dotenv[1]。
這個(gè)庫(kù)使用起來(lái)非常簡(jiǎn)單,只需要兩行代碼加一個(gè)文件。
首先,在項(xiàng)目的根目錄創(chuàng)建一個(gè)文件,叫做.env。使用Windows的同學(xué)可能無(wú)法做到,因?yàn)閃indows使用正常方法沒(méi)有辦法創(chuàng)建一個(gè)點(diǎn)開(kāi)頭的文件。但是Linux和macOS可以正常創(chuàng)建。例如:
- NAME=kingname
- SALARY=9999999
- ADDRESS=上海
然后,在項(xiàng)目入口文件的頂部,增加兩行代碼,如下圖所示:
- from dotenv import load_dotenv
- load_dotenv()
這樣就完成了。你原來(lái)讀取環(huán)境變量的代碼不需要做任何修改,直接讀取環(huán)境變量就可以了,如下圖所示:
從圖中可以看到,當(dāng)我們?cè)赟hell里面直接執(zhí)行echo $ 變量名的時(shí)候,顯示的是空,說(shuō)明這個(gè)環(huán)境變量是沒(méi)有設(shè)置的。當(dāng)我們運(yùn)行項(xiàng)目代碼的時(shí)候,python-dotenv會(huì)自動(dòng)讀取.env文件,然后在項(xiàng)目里面設(shè)置環(huán)境變量。
如果僅僅是讀文件,那我當(dāng)然不會(huì)特意介紹它。它還有兩個(gè)更好用的功能。
如果環(huán)境變量已經(jīng)存在,那么會(huì)以已經(jīng)存在的環(huán)境變量為準(zhǔn),.env中對(duì)應(yīng)的項(xiàng)自動(dòng)失效:
也就是說(shuō),這個(gè).env文件,你甚至可以直接上傳到生產(chǎn)環(huán)境。由于生產(chǎn)環(huán)境已經(jīng)設(shè)置好了對(duì)應(yīng)的配置參數(shù),所以.env文件里面的內(nèi)容自動(dòng)失效。
第二個(gè)好用的功能,是.env里面還可以復(fù)用同一個(gè)變量。例如,我的項(xiàng)目有一個(gè)域名會(huì)在多個(gè)地方用到:
- EMAIL=contact@kingname.info
- ENTRYPOINT=https://kingname.info/api
- REDIS_HOST=redis.kingname.info
- KAFKA_SERVER=kafka.kingname.info
- ...
如果有一天我要修改這個(gè)域名,那么所有配置都需要修改。但是.env可以復(fù)用變量:
- DOMAIN=kingname.info
- EMAIL=contact@${DOMAIN}
- ENTRYPOINT=https://${DOMAIN}/api
- REDIS_HOST=redis.${DOMAIN}
- KAFKA_SERVER=kafka.${DOMAIN}
這樣一來(lái),當(dāng)我要改域名的時(shí)候,只需要修改DOMAIN的值就可以了。
關(guān)于python-dotenv的更多使用說(shuō)明,大家可以閱讀參考文檔里面的Readme。
參考文獻(xiàn)
[1]python-dotenv: https://github.com/theskumar/python-dotenv