LoginSignup
162
145

More than 5 years have passed since last update.

Flaskにおける設定ファイルのベストプラクティス

Posted at

概要

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ファイルの形式で設定を記載できます。

config_file.cfg
TESTING=False
DEBUG=True

オブジェクトからの設定

Pythonのオブジェクトとして設定を読み込むことができます。

オブジェクトからの設定
app.config.from_object('config.BaseConfig')

ソースコード中ではfrom_jsonというのも見えた気がしましたが、無視します。
ファイル内では以下のように、Pythonスクリプトとして設定を構造化できます。

config.py
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:

  • デフォルトの設定ファイルはバージョン管理下に置く
  • デフォルトの設定はオブジェクトとして書き、環境変数を利用して読み込む
  • センシティブな設定はインスタンスフォルダ内の設定で上書きする

最後の項目はdevelopmentproductionなどを切り替えるためですね。
オブジェクトとして記載することにより、テストもしやすくなるはずです。

具体例としては以下のように記載されています。

ベストプラクティス(非公式)
# 基本的な設定はバージョン管理下の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ファイルで設定
  • 複数の環境を用意するレベルならベストプラクティスに従う

というくらいの認識を持ちました。

長々書いてしまいましたが、結局は自分自身が納得できるかどうかですよね。
構成が汚くても、秘密のファイルが流出しなければとりあえずは問題なし。

アプリケーションの拡張に合わせて、より良いかたちを見つけられればと思います。

162
145
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
162
145