概要
Flaskアプリケーションで設定ファイルを作成する際に
環境ごとの分割や内容の隠蔽をどうすればうまくいくかの検討をしていました。
公式ドキュメントと海外の方の記事を読んで思ったことをまとめます。
このページの大部分は以上の2ページの和訳から作られています。
Flaskにおけるconfig
Flaskの設定ファイルで押さえておいたほうが良さそうな部分をまとめます。
基本的な設定
Flask
インスタンスのconfig
変数に辞書形式で書き込むことができます。
app.config['DEBUG'] = True
ファイルからの設定
指定したファイルから設定の一覧を読み込むことができます。
# ファイルパスを直接指定するパターン
app.config.from_pyfile('config_file.cfg')
# ファイルの位置を示す環境変数(絶対パス)を指定するパターン
app.config.from_envvar('FLASK_CONFIG_FILE')
ファイル内では以下のようなINIファイルの形式で設定を記載できます。
TESTING=False
DEBUG=True
オブジェクトからの設定
Pythonのオブジェクトとして設定を読み込むことができます。
app.config.from_object('config.BaseConfig')
ソースコード中ではfrom_json
というのも見えた気がしましたが、無視します。
ファイル内では以下のように、Pythonスクリプトとして設定を構造化できます。
class BaseConfig(object):
DEBUG = False
TESTING = False
class DevelopmentConfig(BaseConfig):
DEBUG = True
TESTING = True
class TestingConfig(BaseConfig):
DEBUG = False
TESTING = True
インスタンスフォルダ
アプリケーション開発の際にはソースのバージョン管理が不可欠ですが
設定ファイルにはパスワードやAPIのアクセスキーなどの
バージョン管理に含めたくない情報が存在します。
Flaskにおいて「インスタンスフォルダ」は
特定の設定ファイルをバージョン管理から除外するための機能です。
Flask
の初期化の際に、絶対パスでインスタンスフォルダを指定できます。
app = Flask(__name__, instance_path='/path/to/instance/folder')
この指定がない場合は、デフォルトのinstance
ディレクトリが
インスタンスフォルダとして認識されます。
以下のように記載した場合はインスタンスフォルダから相対パスで
設定ファイルを読み込むことができます。
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile('application.cfg', silent=True)
ここではinstance/application.cfg
を参照しています。
silent=True
により、ファイルが見つからなかった場合のエラーを抑制しています。
とはいえ、これだけでバージョン管理から除外できるわけではないので
インスタンスフォルダのパスを.gitignore
に記載するのを忘れてはいけません。
ベストプラクティス
公式ページにベストプラクティスの項がありますが
内容は短く、あまり具体的な記載はされていません。
(英語力の問題により、「テストしやすい方が良い」くらいしか読み取れず…)
一方で、こちらの記事では以下のように記載されています。
Good practice is to have a default configuration, which is under source control and to override it with sensitive and specific information kept in instance folders. For the default configuration you could use object-based configuration hierarchy(described in Object-based configuration section) and to manage which configuration object to load via environment variables:
- デフォルトの設定ファイルはバージョン管理下に置く
- デフォルトの設定はオブジェクトとして書き、環境変数を利用して読み込む
- センシティブな設定はインスタンスフォルダ内の設定で上書きする
最後の項目はdevelopment
やproduction
などを切り替えるためですね。
オブジェクトとして記載することにより、テストもしやすくなるはずです。
具体例としては以下のように記載されています。
# 基本的な設定はバージョン管理下のconfig.pyにオブジェクトとして記載
config = {
"development": "bookshelf.config.DevelopmentConfig",
"testing": "bookshelf.config.TestingConfig",
"default": "bookshelf.config.DevelopmentConfig"
}
def configure_app(app):
# 環境変数を利用して読み込む設定ファイルを決定
config_name = os.getenv('FLASK_CONFIGURATION', 'default')
# 設定はオブジェクトとして読み込む
app.config.from_object(config[config_name])
# センシティブな設定はインスタンスフォルダ内の設定で上書きする
app.config.from_pyfile('config.cfg', silent=True)
まとめ
上記の設定をすべてに適用してると大変だと思うので
- Hello World!をやる程度なら
app.config
にベタ書きで指定 - 個人で作るような小さめのアプリケーションなら
config
ファイルで設定 - 複数の環境を用意するレベルならベストプラクティスに従う
というくらいの認識を持ちました。
長々書いてしまいましたが、結局は自分自身が納得できるかどうかですよね。
構成が汚くても、秘密のファイルが流出しなければとりあえずは問題なし。
アプリケーションの拡張に合わせて、より良いかたちを見つけられればと思います。