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

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

Flaskではアプリの構成をさまざまな方法で行える。その基本からインスタンスフォルダを利用するまでざっくりと見ていこう。

[かわさきしんじ,Insider.NET編集部]
「Visual Studio Codeで始めるPythonプログラミング」のインデックス

連載「Visual Studio Codeで始めるPythonプログラミング」

 前回は、データベースに保存されたデータをWeb APIを介してクライアントに返送する方法を幾つか示した。今回は、Flaskアプリの構成方法について見ていこう(タイトルとは裏腹にVisual Studio Codeの話題はほとんど出てこない)。

Flaskアプリの構成方法

 Webアプリに限らず、アプリには構成(configuration)が必要になる。開発環境でデバッグ実行をしているのか、プロダクション環境で実行をしているのかなど、その実行環境によって、アプリの振る舞いを変更する必要があるからだ。

 Flaskアプリでは、幾つかの方法でその構成を行える。一番簡単なのは、本連載で既に見てきたものだ。以下に例を示す(「VS CodeとFlask-SQLAlchemyでデータベース操作 」の「最小限のアプリ」より)。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db/sample.db"
db = SQLAlchemy(app)

Flaskアプリで使用するデータベースの構成を行っているところ

 これはapp.configオブジェクトを利用して、SQLALCHEMY_DATABASE_URIの値を「sqlite:///db/sample.db」に設定するものだ。

 小規模なアプリや本連載で紹介しているような「サンプル」であれば、上のようにハードコードしても問題ないだろう。だが、環境に応じて構成を変える必要があるのであれば、Flaskではさまざまな方法でアプリを構成できるようになっている。大ざっぱにいえば、Flaskアプリは以下のような方法で構成可能だ。

  • 構成ファイルを使った構成(from_pyfile、from_json)
  • 環境変数を使った構成(from_envvar)
  • Pythonオブジェクトを使った構成(from_object)
  • マッピングを使った構成(from_mapping)
  • インスタンスフォルダを使った構成

 このうち、インスタンスフォルダを使った構成は、アプリに固有の機密性を持った情報をアプリ本体からは隔離しておくことを目的としている(シークレットキーなどをアプリ本体からは独立したフォルダに保存して、ソースコード管理の対象から外すといった利用法を想定している)。

 本稿ではこれらの方法の幾つかを紹介しよう。

本稿で作成するアプリ

 これまでのToDoリストアプリから外れて、今回は以下のようなアプリを作成する。今回はWindows版のPython 3.6.5を使用して仮想環境「myenv」を作成した後に、そこに「pip install flask」コマンドでFlaskをインストールしている。また、動作確認もWindows版のVS Codeで行っている。

今回作成するアプリの基本構造 今回作成するアプリの基本構造

 今回は「パッケージ形式」の構成を取り、アプリ本体は__init__.pyファイルに記述する。パッケージ名は「flask_app」となっている。その基本コードは次の通りだ。

from flask import Flask, render_template

app = Flask(__name__)

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

今回作成するFlaskアプリ

 アプリのルートへのリクエストを受け取ると、app.configオブジェクトに登録されている構成値をテンプレートを利用して表示するだけの簡単なものだ。構成値の表示に使用するテンプレートは次のようになっている。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>Configuration setted up by Flask</title>
</head>

<body>
  {% for key, value in config %} {{ key }}: {{ value }}<br> {% endfor %}
</body>

</html>

構成値の表示に使用するテンプレート

 [デバッグ]ビューで歯車アイコンをクリックしてlaunch.jsonファイルを作成したら、Flask用のデバッグ構成にある「FLASK_APP」環境変数の値をパッケージ名である「flask_app」に変更するのを忘れないようにしよう(あるいは、コマンドパレットから[Python: Create Terminal]コマンドを実行して仮想環境を有効にしたターミナルを開いてから、FLASK_APP環境変数の値を設定し、「flask run」コマンドでアプリを起動してもよい)。

{
  "version": "0.2.0",
  "configurations": [
    // …… 省略 ……
    {
      "name": "Python: Flask (0.11.x or later)",
      "type": "python",
      "request": "launch",
      "module": "flask",
      "env": {
        "FLASK_APP": "flask_app"
      },
      "args": [
        "run",
        "--no-debugger",
        "--no-reload"
      ]
    },
    // …… 省略 ……
  ]
}


launch.jsonファイルの内容(抜粋)

 この状態でアプリを実行したところを以下に示す。

デフォルトで設定されているFlaskアプリの構成値が表示されたところ デフォルトで設定されているFlaskアプリの構成値が表示されたところ

 表示されている構成値(組み込みの構成値)については、「Builtin Configuration Values」を参照されたい(英語ページ)。重要なのは、ENVやDEBUGといった構成値は環境変数FLASK_ENV/FLASK_DEBUGを用いて設定するものであり、アプリ内のコードでこれらを設定しても「思った通りの動作とはならない」ことだ(上記ページに明記されている)。

 では、このアプリを使って、各種の構成方法を試していこう。

ファイルを利用した構成

 app.config.from_pyfileメソッドを使うと、構成値を「キー=値」形式で記述したファイルを基に構成値を設定できる。以下に例を示す。

from flask import Flask, render_template

app = Flask(__name__)
app.config["SOME_CONFIG"] = "configured in __init__.py"
app.config.from_pyfile("config.cfg", silent=True)

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

SOME_CONFIG = "configured in config.cfg"


構成ファイルを利用するコードを追記した__init__.pyファイル(上)と、構成値を列挙したconfig.cfgファイル(下)

 ここでは、__init__.pyファイルで"SOME_CONFIG"の値を"configured in __init__.py"に設定した上で、構成を記述したconfig.cfgファイルでも「"configured in config.cfg"」のようにして構成している。from_pyfileメソッドのsilent引数にTrueを渡しているが、これはファイルがなかったときに例外を発生しないようにするものだ。この状態でアプリを実行すると、次のようになる。

config.cfgファイルにより__init__.pyで行った構成が上書きされた(最下部に注目) config.cfgファイルにより__init__.pyで行った構成が上書きされた(最下部に注目)

 一番下の行を見ると分かるように、構成値が上書きされたことが分かる(もちろん、2行の順序を入れ替えれば、後の構成で先の構成が上書きされる)。ここから分かるのは、アプリの実行環境によらず共通の構成値を何らかの方法で設定した後に、実行環境ごとに異なる構成を行うといったことがFlaskでは可能ということだ。

 ファイルから構成値を読み込むにはfrom_envvarメソッドも使える。これは引数に指定した環境変数の値を基に読み込み対象のファイルを決定するものだ。よって、開発時と運用時で環境変数が指すファイルを別個にすることで、基本構成をそれぞれの設定で上書きしたり、環境に固有の構成を行ったりできる。ここではanother_config.cfgファイルを作成して、環境変数ANOTHER_CONFIG_FILEにそのファイルを指定してみよう。

from flask import Flask, render_template

app = Flask(__name__)
app.config["SOME_CONFIG"] = "configured in __init__.py"
app.config.from_pyfile("config.cfg", silent=True)
app.config.from_envvar("ANOTHER_CONFIG_FILE")

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

SOME_CONFIG = "configured in another_config.cfg"
ANOTHER_CONFIG = "another config"


環境変数を介して構成ファイルを指定するコード(上)ともう1つの構成ファイル(another_config.cfgファイル。下)

 実行結果を以下に示す。

another_config.cfgファイルに記述した構成値が表示されたところ(最下部) another_config.cfgファイルに記述した構成値が表示されたところ(最下部)

 from_jsonメソッドも同様で、JSON形式で書かれた構成ファイルを読み込ませるのに使用できる(興味のある方は試してみよう)。次にPythonオブジェクトを使用した構成について見ていこう。

       1|2 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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