はじめに
今まで開発環境、テスト環境、本番環境全てで同じ設定ファイルを使いまわしていて、都度パラメータを書き換えていました。
しかし2018年にもなってその運用はナンセンスと思い直しまして、設定ファイルの自動切換えを検討しました。
モジュールや事例を探しましたがDjangoの記事が数件引っかかるのみで良いものも無かった為、自力で作ってみました。
ファイル構成
.
├── config
│ ├── development.py
│ ├── __init__.py
│ ├── production.py
│ └── test.py
├── hoge.py
├── main.py
└── tests
└── test_hoge.py
2 directories, 7 files
configディレクトリ
設定ファイルをまとめて入れておくディレクトリです。
今回設定ファイルとしてpythonスクリプトをそのまま使いましたが、
好みに合わせてini
なりjson
なりyaml
なり置き換えて貰えればいいと思います。
設定ファイル
各環境の設定ファイルです。
とりあえずENV
という設定値のみ記述してあります。
ENV = 'production'
ENV = 'development'
ENV = 'test'
設定ファイルの振り分け
configモジュールの__init__.py
に振り分け処理を書いていきます。
ちょっとごちゃごちゃしてますが、引数に応じてimportする設定ファイルを変えているだけです。
import sys
import argparse
if 'unittest' in sys.argv[0]:
from config.test import *
else:
parser = argparse.ArgumentParser()
parser.add_argument(
"-p",
"--production",
action="store_true",
help="use production config")
parser.add_argument(
"-d",
"--development",
action="store_true",
help="use development config")
parser.add_argument(
"-t", "--test", action="store_true", help="use test config")
args = parser.parse_args()
if args.production:
from config.production import *
elif args.development:
from config.development import *
elif args.test:
from config.test import *
else:
from config.development import *
__init__.py
にこんな処理を書くのってそもそもどうなんだろう…?
__init__.py
って大体空ファイルか、import文をまとめて書いているような使い方しか見たことが無い。
このような処理、ましてはargparse
を書くのはすごく作法に反している気がする…!
実装サンプル
設定ファイルのENV
値を呼び出すだけのクラスと、そのクラスを使うだけのスクリプトを作ります。
""" ENVを呼び出すだけのクラス """
from config import *
class Hoge():
def print_env(self):
print(ENV)
def env(self):
return ENV
""" Hoge#print_envを呼ぶだけのスクリプト """
from hoge import Hoge
if __name__ == '__main__':
hoge = Hoge()
hoge.print_env()
テストサンプル
unittest用のテストスクリプトです。
Hoge#env
で'test'
を返すかどうかをテストします。
import unittest
from hoge import Hoge
class TestHoge(unittest.TestCase):
""" test class """
def test_env(self):
""" hoge test """
hoge = Hoge()
env = hoge.env()
self.assertEqual(env, 'test')
if __name__ == "__main__":
unittest.main()
実行例
普通に実行
なにも指定しないで実行するとdevelopment
環境の設定ファイルが使用されます。
> python main.py
development
開発環境を明示して実行
オプション-d
(もしくは--development
)を指定してもdevelopment
環境の設定ファイルが使用されます。
省略しても同じなのであんまり意味無いです、コレ。
> python main.py -d
development
本番環境で実行
オプション-p
(もしくは--production
)を指定するとproduction
環境の設定ファイルが使用されます。
本番環境はうっかり実行はしたくないので引数での明示が必須です。
> python main.py -p
production
テスト環境で実行
unittest
で実行するとtest
環境の設定ファイルが使用されます。
> python -m unittest tests.test_hoge
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
イケてないところ
他にいい方法が思いつかなかったとはいえ、configモジュールでargparse
を使って分岐している点がイケてないです。
main.py
などで引数を定義することができなくなってしまっています。
個人的にはargparse
自体あまり使う機会がないので困らないんですが…この設計はイケてない…
さいごに
もっと簡単に実現できるモジュールとか無いかな?