Read Configuration - minnie0531/fastapi-template GitHub Wiki

python์—์„œ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ configuration์„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Š” ํŒŒ์ผ์„ ํ˜•ํƒœ๋‚˜ ์‚ฌ์šฉ์ž์˜ ์˜๋„์— ๋”ฐ๋ผ ๊ฒฐ์ •๋œ๋‹ค. ํฌ๊ฒŒ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ฝ๋Š” ๋ฐฉ๋ฒ•๊ณผ ํŒŒ์ผ๋กœ ์ฝ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๊ณ , ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ configuration๋“ค์ด ์„ค์ •๋  ๊ฒฝ์šฐ os.getenv("VARIABLE_NAME") ์œผ๋กœ ๊ฐ’์„ ๊ฐ€์ ธ ์˜ค๋ฉด ๋œ๋‹ค.

ํŒŒ์ผ๋กœ ์ฝ๋Š” ๋ฐฉ๋ฒ•์€ json์ด๋‚˜ yaml ํ˜•ํƒœ๋Š” json์ด๋‚˜ pyyaml์„ ํ†ตํ•ด ์ฝ๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋™์ผ ํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—์„œ๋Š” pydantic์˜ settings๋ฅผ ์ด์šฉํ•œ .env ํŒŒ์ผ ์ฝ๋Š” ๋ฐฉ๋ฒ•๊ณผ configparser์™€ jpproperties๋ฅผ ์ด์šฉํ•œ python config ํŒŒ์ผ์ฝ๊ธฐ๋ฅผ ๋‹ค๋ฃฐ ์˜ˆ์ •์ด๋‹ค.

Use Pydantic settings

FastAPI๋ฅผ ์‚ฌ์šฉ๊ฒŒ ๋˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ pydantic์˜ model์„ business๋ชจ๋ธ๋กœ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด์„œ configuration์„ ๊ตฌํ˜„ ํ•œ๋‹ค๋ฉด ์ผ์ข…์˜ ํ†ต์ผ๊ฐ์„ ์ฃผ๋Š” ๋งˆ์Œ์˜ ์•ˆ์ •(?)์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๋ฒˆ ์‹œ๋„ ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

pydatic์˜ ๊ฒฝ์šฐ python ๋ชจ๋“ˆ ์ค‘ python-dotenv๋ฅผ ์ด์šฉํ•˜์—ฌ .env๋ฅผ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

  1. db_confg.env ์ค€๋น„
HOST="localhost"
PORT=1521
SID="ORACLE"
USER_ID="aaa"
USER_PW="1234"
  1. Create Settings class
from pydantic import BaseSettings

class Settings(BaseSettings):
    host: str
    port: int
    sid: str
    user_id: str
    user_pw: str
   
    class Config:
        env_file = 'db_config.env'
        env_file_encodeing = 'utf-8'
  1. Create Settings instance and get values
settings = Settings(_env_file='./app/config/db_config.env')

dsn = cx_Oracle.makedsn(host=**settings.host**, port=**settings.port**, sid=**settings.sid**)
engine = create_engine("oracle+cx_oracle://%s:%s@%s" % (**settings.user_id**, **settings.user_pw**, str(dsn)))

์‚ฌ์šฉ๋ฐฉ๋ฒ•์ด ์–ด๋ ต์ง€ ์•Š์ง€๋งŒ setting์— ๋Œ€ํ•œ ๋ชจ๋ธ์„ ๋‹ค์‹œํ•œ๋ฒˆ ์ •์˜ ํ•˜๊ณ  ๋“ค์–ด๊ฐ„๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์€ ์–ด๋–ค ์š”์†Œ๋“ค์ด ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ๋ช…์‹œ์ ์ด์ง€๋งŒ, ํ•œํŽธ์œผ๋กœ๋Š” ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•  ๋•Œ ํŒŒ์ผ์„ ํ•˜๋‚˜ ๋” ๋ณด๊ฒŒ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ๋‹ค. configuration๋“ค์€ ๋Œ€๊ฒŒ ๋ฐ”๋กœ ์•Œ์•„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋“ค์„ ์„ ํƒํ•˜๊ณ  ์žˆ๊ธฐ๋„ ํ•˜๊ณ  ์ด๋ฏธ ์•Œ๊ณ  ์ •์˜๋œ ๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ฝ”๋“œ๋ฅผ ์ฝ๊ธฐ ํŽธํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•๋ณด๋‹ค๋Š” ๋‹ค์ด๋ ‰ํŠธ๋กœ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์„ ํ˜ธ ํ•œ๋‹ค. (๊ฐœ์ธ์ ์ธ ์ฐจ์ด๋‹ค)

Use configParser

  1. Use db_config.env but add section on the config and remove quotation marks " '

Quotation mark๋„ ๊ฐ™์ด ์ฝ์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ์ง€์›Œ์ฃผ๋Š” ๊ฒŒ ์ข‹์Œ

**[db]**
HOST=localhost
PORT=1521
SID=ORCLCDB
USER_ID=aaa
USER_PW=1234
  1. Declare configParser and read file and attributes

๊ธฐ๋ณธ์ ์œผ๋กœ string์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ฃผ๊ธฐ๋•Œ๋ฌธ์— int๋กœ ์ฝ์–ด๊ฐ€์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ํ˜•๋ณ€ํ™˜์ด ํ•„์š”๋กœํ•จ.

parser = ConfigParser()
parser.read(r'./app/config/db_config.env')

dsn = cx_Oracle.makedsn(host=parser.get('db', 'host'), port=int(parser.get('db', 'port')), sid=parser.get('db',  'sid'))
engine = create_engine("oracle+cx_oracle://%s:%d@%s" % (parser.get('db','user_id'), int(parser.get('db','user_pw')), str(dsn)))

Kubernetes์—์„œ configMap ์˜ ๊ฒฝ์šฐ ๋Œ€๋ถ€๋ถ„ propertiesํŒŒ์ผ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋Š” ์ฒ˜์Œ ์‚ฌ์šฉํ•œ db_cofnig.env์— ๊ฐ€๊น๋‹ค. sectionํŒŒํŠธ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— configParser๋ฅผ ์ด์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค. configparser.MissingSectionHeaderError: File contains no section headers

๊ทธ๋ž˜์„œ section์ด ์—†์„ ๊ฒฝ์šฐ string ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  section์ถ”๊ฐ€ํ›„ configParser๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.(์˜ˆ์˜์ง€ ์•Š๋‹ค..)

User jproperties

confgMap์œผ๋กœ ์ €์žฅ๋œ properties ํŒŒ์ผ์„ ์ฝ์–ด ๊ฐ–๊ณ  ์˜ค๊ธฐ์— ๊ฐ€์žฅ ํŽธํ•œ ๋ฐฉ๋ฒ•์ด ์•„๋‹๊นŒ ์ƒ๊ฐ๋œ๋‹ค. ๋”ฐ๋กœ ๋ชจ๋ธ์— ๋Œ€ํ•œ ๊ตฌํ˜„ ์—†์ด ๊ฐ’์„ getํ•˜์—ฌ ๊ฐ€์ ธ ์˜ฌ ์ˆ˜ ์žˆ๊ณ  ์ถ”๊ฐ€์ ์œผ๋กœ section์„ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ๋„ ์—†๋‹ค.

  1. pip install jproperties
  2. user original db_config.env
HOST=localhost
PORT=1521
SID=ORCLCDB
USER_ID=aaa
USER_PW=1234
  1. Declare properties and get the values
from jproperties import Properties
 
configs = Properties()

with open('./app/config/db_config.env', 'rb') as config_file:
    configs.load(config_file)

dsn = cx_Oracle.makedsn(host=configs.get('HOST').data, port=int(configs.get('PORT').data), sid=configs.get('SID').data)
engine = create_engine("oracle+cx_oracle://%s:%d@%s" % (configs.get('USER_ID').data, int(configs.get('USER_PW').data), str(dsn)))

๊ตฌํ˜„์ด๋‚˜ ๊ฐ€๋…์„ฑ์— ์žˆ์–ด์„œ ์žฅ์ ์ด ์žˆ์ง€๋งŒ, ์•ž์˜ ๋จผ์ € ๋ณด์—ฌ์ค€ ์˜ˆ์ œ์™€ ๋‹ฌ๋ฆฌ, ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•ด์•ผ ํ•œ๋‹ค.

ํŒŒ์ผ์„ ์ฝ์–ด์„œ configuration์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ์ ์šฉํ•ด๋ณด์ž!