flaskでconfigファイルの指定に物理的なパスを指定できるようにしたくなったという話
はじめに
flaskを使い始めたのだけれど。flaskのconfigファイルの指定が対象のflaskアプリの存在するモジュールの位置からの相対パスを指定するらしく使いづらい。
例えば、fooパッケージの中で、以下の様なコードがあった場合には、fooパッケージからの相対位置を指定する必要がある。
from flask import Flask app = Flask(__name__) app.config.from_python("<config path>") app.run()
この __name__
を使っているパッケージの位置からの相対位置を指定する必要がある。だるい。これを止めて直接特定のファイルの位置を指定できるようにしようという話。
Appのconfig_classを変更すれば良い
はじめに手抜きをするために以下のmagicalimportというパッケージをインストールしておく*1。
$ pip install magicalimport
configオブジェクトを作るファクトリーの設定を変更する必要がある。以下の様な形で作れば良い。
from flask import Flask, Config import logging import magicalimport logger = logging.getLogger(__name__) class CustomConfig(Config): def from_pyfile(self, path): return self.from_object(magicalimport.import_from_physical_path(path)) class App(Flask): config_class = CustomConfig # or monkey patching # Flask.config_class = CustomConfig if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("-c", "--config", default=None, required=True) args = parser.parse_args() app = App(__name__) if args.config: app.config.from_pyfile(args.config) logging.basicConfig( level=app.config["LOGGING_LEVEL"].upper(), format=app.config["LOGGING_FORMAT"] ) logger.info("running.. (port=%s)", app.config["PORT"]) app.run(port=app.config["PORT"])
あとは以下のように好きな位置のファイルを指定してアプリを起動する事ができる。
$ tree config config ├── base.py └── local.py 1 directory, 2 files $ python foo/app.py --config=./config/local.py asctime2016-10-02 00:52:40,828 loglevel:INFO message:running.. (port=8888) asctime2016-10-02 00:52:40,847 loglevel:INFO message: * Running on http://127.0.0.1:8888/ (Press CTRL+C to quit)
やりましたね。
設定ファイルの内容
設定ファイルの内容は以下
config/base.py
PLAIN_LOGGING_FORMAT = "%(asctime)s %(levelname)s %(message)s" LTSV_LOGGING_FORMAT = "asctime%(asctime)s\tloglevel:%(levelname)s\tmessage:%(message)s"
config/local.py
import magicalimport import os.path here = os.path.dirname(os.path.abspath(__file__)) base = magicalimport.import_from_physical_path(os.path.join(here, "./base.py"), as_="base") LOGGING_LEVEL = "info" LOGGING_FORMAT = base.LTSV_LOGGING_FORMAT PORT = 8888
*1:実はこのためについ先程作りました