連載
» 2018年08月28日 05時00分 公開

Visual Studio Codeで始めるPythonプログラミング:VS CodeとPythonで作るFlaskアプリの構成を一巡り (2/2)

[かわさきしんじ,Insider.NET編集部]
前のページへ 1|2       

Pythonオブジェクトを利用した構成

 Pythonオブジェクトを利用した構成といっても、基本はファイルを利用した場合と同様だ。from_objectメソッドに.pyファイルを渡すだけだ。ただし、こちらではPythonのモジュールやクラスを渡すことができる。ここではconfig.pyファイルに構成値を記述するものとして、以下にそのコード例を示す(Flaskのドキュメント「Development / Production」に掲載されているコードを改変したもの)。

SOME_CONFIG = "configured in config.py"

class Config(object):
  DEBUG = False
  TESTING = False
  DATABASE_URI = 'sqlite:///:memory:'
  SOME_CONFIG = "configured in Config class in config.py"

class ProductionConfig(Config):
  DATABASE_URI = 'mysql://user@localhost/foo'
  SOME_CONFIG = "configured in ProductionConfig class in config.py"

class DevelopmentConfig(Config):
  DEBUG = True
  SOME_CONFIG = "configured in DevelopmentConfig class in config.py"

基底クラスで基本構成を、派生クラスで環境ごとの構成を行う例(config.pyファイル)

 モジュールトップレベルと各クラスでSOME_CONFIGを定義している。また、構成の基底クラスとなるConfigクラスとプロダクション構成を示すProductionConfigクラスではDATABASE_URIが異なる値になっている。このような構成にすることで、デフォルトの構成/環境ごとの構成を切り分けられる(が、読み込む構成は以下に示すようにハードコードすることになるのであまり意味はないかもしれない)。

 これらの構成をアプリで読み込むには以下のようにする(ここではfrom_pyfileなどのメソッド呼び出しは削除した)。

from flask import Flask, render_template

app = Flask(__name__)
app.config.from_object("flask_app.config.DevelopmentConfig")

@app.route("/")
def index():
  return render_template("index.html", config=app.config.items())

configモジュールで定義したDevelopmentConfigクラスを使用して構成を行うコード(__init__.pyファイル)

 from_objectメソッドには上のコード例のように「パッケージ.モジュール.クラス名」あるいは「モジュール.クラス名」といった形式で利用するクラスやモジュールを文字列形式で渡せる。あるいは、次のようにクラスオブジェクトを渡してもよい。

from flask import Flask, render_template
from flask_app.config import DevelopmentConfig

app = Flask(__name__)
app.config.from_object(DevelopmentConfig)

@app.route("/")
def index():
  return render_template("index.html", config=app.config.items())

クラスオブジェクトを渡す例

 実行結果を以下に示す。

DevelopmentConfigクラスで定義されている構成値が表示されたところ(最下部) DevelopmentConfigクラスで定義されている構成値が表示されたところ(最下部)

 最下部の2行を見ると、DATABASE_URIの値は基底クラスのものが使われ、SOME_CONFIGの値はDevelopmentConfigクラスで定義したものが使われている。

 ただし、上のコードを見ても分かるように、これでは構成をアプリ内にハードコードすることになってしまうことには注意しよう。実際、from_objectメソッドのドキュメントでは「デフォルトの構成ではなく、実際に使用する構成を読み込むのにこの関数を使うべきではない。実際に使用する構成はfrom_pyfileメソッドを使って、理想をいえば、アプリのパッケージとは異なる場所から読み込むべき」とある(筆者による意訳)。

 そのため、from_objectメソッドを使用する場合の理想形は、(今のところ)以下のようなコードになる。

from flask import Flask, render_template
import os

app = Flask(__name__)
app.config.from_object("flask_app.config.Config"# デフォルトの構成値
app.config.from_pyfile(os.environ["APP_SETTINGS"])  # 環境固有の構成値
#app.config.from_envvar("APP_SETTINGS")  # 上の行と同じ

@app.route("/")
def index():
  return render_template("index.html", config=app.config.items())

デフォルト値をfrom_objectで読み込み、from_pyfileで環境固有の構成値を読み込む

 上のコードで行っている「app.config.from_pyfile(os.environ["APP_SETTINGS"])」はコメントアウトしてある「app.config.from_envvar("APP_SETTINGS")」と同値だ。

 環境変数APP_SETTINGSで「アプリ本体(パッケージ)とは異なるフォルダ」にあるファイルを指定することで、(特に機密性のある)構成ファイルをアプリから分離できるようになる。

 これを簡単に行うための機構が最後に紹介する構成方法である「インスタンスフォルダ」だ。

インスタンスフォルダを使用した構成

 「インスタンスフォルダ」とは、機密性のある構成情報(データベースやWeb APIへのアクセスに必要なキー、クッキーの署名に必要となるシークレットキーなど)を保存するための場所として想定されており、このフォルダはソース管理の対象から外すものとされている。また、環境固有の設定値などもこのフォルダに置くことが推奨されている。

 インスタンスフォルダを指定するには、Flaskクラスのコンストラクタでアプリインスタンスを初期化する際に、そのフルパスを指定するか、instance_relative_configスイッチをTrueに設定する。ここでは後者の方法でインスタンスフォルダを使ってみよう。

from flask import Flask, render_template
import os

app = Flask(__name__, instance_relative_config=True)
app.config.from_object("flask_app.config.Config"# デフォルト
app.config.from_pyfile("config.cfg")  # instance/config.cfgファイルから読み込み

@app.route("/")
def index():
  return render_template("index.html", config=app.config.items())

インスタンスフォルダを使用するように修正したコード(__init__.pyファイル)

 上のコードでは、Flaskクラスのコンストラクタでinstance_relative_configスイッチをTrueにしている。この場合、パッケージと同レベルにある「instance」フォルダが「インスタンスフォルダ」として扱われる。そこで、このフォルダを作成して、そこにconfig.cfgファイルを置いてみる。

最終的なフォルダ構成 最終的なフォルダ構成

 config.cfgファイルの内容は以下のようにしておこう。

SOME_CONFIG = "configured in instance/config.cfg"


instance/config.cfgファイルの内容

 「app.config.from_object(……)」で読み込むデフォルト構成を記述したファイル(config.pyファイル)は、これまで通り、アプリのパッケージ内に置いておけばよい。

 実行結果を以下に示す。

instance/config.cfgファイルから構成値が読み込まれた(最下部) instance/config.cfgファイルから構成値が読み込まれた(最下部)

 最下部を見ると、SOME_CONFIGの値が「configured in instance/config.cfg」となっていることから、この値がinstance/config.cfgファイルから読み込まれたことが分かる。その一方で、DATABASE_URIの値はflask_appパッケージ内にあるconfig.pyファイルのConfigクラスで定義されたものとなっている。

 なお、Flaskのドキュメント「Development / Production」では以下のような事項が推奨されているので、興味のある方はドキュメントにも目を通しておこう(プロダクションレベルのコードや構成をプッシュする方法についても推奨事項があるが、ここでは割愛)。

  • デフォルト構成はバージョン管理の下に置く
  • 構成の切り替えには環境変数を使用する。Pythonコードの外部でこれを行うことで、構成の切り替えを簡単に、コードに手を付けることなく行える

 このポリシーに従い、環境変数とfrom_envvarメソッドを利用して、インスタンスフォルダ内にある各種環境用の構成を切り替えるようにすることで、安全かつ柔軟性を持った形でFlaskアプリの構成を行えるようになるはずだ。


 今回はFlaskアプリの構成をどのように行えばよいかを見てきた。なお、Flaskアプリの構成については「Flaskにおける設定ファイルのベストプラクティス」と「explore-flask-ja/configuration.md」も参考になるので、ぜひ参考にしてほしい。次回はFlaskアプリのデプロイについて見ていく予定だ。

「Visual Studio Codeで始めるPythonプログラミング」のインデックス

Visual Studio Codeで始めるPythonプログラミング

前のページへ 1|2       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。