構成の処理
アプリケーションには、なんらかの構成が必要です。 デバッグモードの切り替え、秘密鍵の設定など、アプリケーション環境に応じて変更する必要のあるさまざまな設定があります。
Flaskの設計方法では、通常、アプリケーションの起動時に構成を使用できるようにする必要があります。 コード内の構成をハードコーディングできます。これは、多くの小さなアプリケーションにとって実際にはそれほど悪くはありませんが、より良い方法があります。
構成のロード方法とは関係なく、ロードされた構成値を保持する使用可能な構成オブジェクトがあります。Flask
オブジェクトのconfig
属性。 これは、Flask自体が特定の構成値を配置する場所であり、拡張機能が構成値を配置できる場所でもあります。 しかし、これはあなたがあなた自身の構成を持つことができる場所でもあります。
構成の基本
config
は実際には辞書のサブクラスであり、他の辞書と同じように変更できます。
app = Flask(__name__)
app.config['TESTING'] = True
特定の構成値もFlask
オブジェクトに転送されるため、そこから読み取りと書き込みを行うことができます。
app.testing = True
複数のキーを一度に更新するには、dict.update()
メソッドを使用できます。
app.config.update(
TESTING=True,
SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/'
)
環境とデバッグ機能
ENV および DEBUG の構成値は、アプリのセットアップ開始後に変更すると動作に一貫性がなくなる可能性があるため、特別です。 環境とデバッグモードを確実に設定するために、Flaskは環境変数を使用します。
この環境は、Flask、拡張機能、およびSentryなどの他のプログラムに、Flaskが実行されているコンテキストを示すために使用されます。 FLASK_ENV
環境変数で制御され、デフォルトはproduction
です。
FLASK_ENV
をdevelopment
に設定すると、デバッグモードが有効になります。 flask run
は、デバッグモードでデフォルトでインタラクティブデバッガーとリローダーを使用します。 これを環境とは別に制御するには、 FLASK_DEBUG
フラグを使用します。
バージョン1.0で変更:デバッグモードとは別に環境を制御するために FLASK_ENV
を追加しました。 開発環境では、デバッグモードが有効になります。
Flaskを開発環境に切り替えてデバッグモードを有効にするには、 FLASK_ENV
を設定します。
$ export FLASK_ENV=development
$ flask run
(Windowsでは、export
の代わりにset
を使用してください。)
上記のように環境変数を使用することをお勧めします。 構成またはコードで ENV および DEBUG を設定することは可能ですが、これは強くお勧めしません。 flask
コマンドで早期に読み取ることはできません。また、一部のシステムまたは拡張機能は、以前の値に基づいて既に構成されている場合があります。
組み込みの構成値
次の構成値は、Flaskによって内部的に使用されます。
- ENV
アプリが実行されている環境。 Flaskと拡張機能は、デバッグモードの有効化など、環境に基づいた動作を有効にする場合があります。
env
属性は、この構成キーにマップされます。 これはFLASK_ENV
環境変数によって設定され、コードで設定されている場合は期待どおりに動作しない可能性があります。本番環境にデプロイするときは、開発を有効にしないでください。
デフォルト:
'production'
バージョン1.0の新機能。
- DEBUG
デバッグモードが有効かどうか。
flask run
を使用して開発サーバーを起動すると、未処理の例外に対して対話型デバッガーが表示され、コードが変更されるとサーバーが再ロードされます。debug
属性は、この構成キーにマップされます。 これは、 ENV が'development'
であり、FLASK_DEBUG
環境変数によってオーバーライドされる場合に有効になります。 コードで設定すると、期待どおりに動作しない場合があります。本番環境にデプロイするときは、デバッグモードを有効にしないでください。
デフォルト: ENV が
'development'
の場合はTrue
、それ以外の場合はFalse
。
- TESTING
テストモードを有効にします。 例外は、アプリのエラーハンドラーによって処理されるのではなく、伝播されます。 拡張機能は、テストを容易にするために動作を変更する場合もあります。 独自のテストでこれを有効にする必要があります。
デフォルト:
False
- PROPAGATE_EXCEPTIONS
例外は、アプリのエラーハンドラーによって処理されるのではなく、再発生します。 設定されていない場合、
TESTING
またはDEBUG
が有効になっていると、これは暗黙的に真になります。デフォルト:
None
- PRESERVE_CONTEXT_ON_EXCEPTION
例外が発生したときにリクエストコンテキストをポップしないでください。 設定されていない場合、
DEBUG
がtrueの場合にtrueになります。 これにより、デバッガーはエラーに関する要求データをイントロスペクトでき、通常は直接設定する必要はありません。デフォルト:
None
- TRAP_HTTP_EXCEPTIONS
HTTPException
タイプの例外のハンドラーがない場合は、単純なエラー応答として返すのではなく、対話型デバッガーによって処理されるように再レイズします。デフォルト:
False
- TRAP_BAD_REQUEST_ERRORS
args
やform
などのリクエスト辞書から存在しないキーにアクセスしようとすると、400 BadRequestエラーページが返されます。 これを有効にすると、エラーが未処理の例外として扱われ、インタラクティブデバッガーが取得されます。 これはTRAP_HTTP_EXCEPTIONS
のより具体的なバージョンです。 設定されていない場合、デバッグモードで有効になります。デフォルト:
None
- SECRET_KEY
セッションCookieに安全に署名するために使用され、拡張機能またはアプリケーションによるその他のセキュリティ関連のニーズに使用できる秘密鍵。 Unicodeも受け入れられますが、ランダムな長いバイト文字列である必要があります。 たとえば、これの出力を設定にコピーします。
python -c 'import os; print(os.urandom(16))' b'_5#y2L"F4Q8z\n\xec]/'
質問を投稿したりコードをコミットしたりするときは、秘密鍵を明かさないでください。
デフォルト:
None
- SESSION_COOKIE_NAME
セッションCookieの名前。 同じ名前のCookieを既にお持ちの場合は変更できます。
デフォルト:
'session'
- SESSION_COOKIE_DOMAIN
セッションCookieが有効になるドメイン一致ルール。 設定されていない場合、Cookieは SERVER_NAME のすべてのサブドメインで有効になります。
False
の場合、Cookieのドメインは設定されません。デフォルト:
None
- SESSION_COOKIE_PATH
セッションCookieが有効になるパス。 設定されていない場合、Cookieは
APPLICATION_ROOT
または/
の下で有効になります(設定されていない場合)。デフォルト:
None
- SESSION_COOKIE_HTTPONLY
ブラウザは、セキュリティのために「HTTPのみ」とマークされたCookieへのJavaScriptアクセスを許可しません。
デフォルト:
True
- SESSION_COOKIE_SECURE
ブラウザは、Cookieが「安全」とマークされている場合にのみ、HTTPSを介したリクエストでCookieを送信します。 これを理解するには、アプリケーションをHTTPS経由で提供する必要があります。
デフォルト:
False
- SESSION_COOKIE_SAMESITE
外部サイトからのリクエストでCookieを送信する方法を制限します。
'Lax'
(推奨)または'Strict'
に設定できます。 Set-Cookieオプションを参照してください。デフォルト:
None
バージョン1.0の新機能。
- PERMANENT_SESSION_LIFETIME
session.permanent
がtrueの場合、Cookieの有効期限はこの秒数後に設定されます。datetime.timedelta
またはint
のいずれかになります。FlaskのデフォルトのCookie実装は、暗号署名がこの値より古くないことを検証します。
デフォルト:
timedelta(days=31)
(2678400
秒)
- SESSION_REFRESH_EACH_REQUEST
session.permanent
がtrueの場合に、すべての応答でCookieを送信するかどうかを制御します。 毎回Cookieを送信すると(デフォルト)、セッションの期限切れをより確実に防ぐことができますが、より多くの帯域幅を使用します。 非永続セッションは影響を受けません。デフォルト:
True
- USE_X_SENDFILE
ファイルを提供するときは、Flaskでデータを提供する代わりに、
X-Sendfile
ヘッダーを設定します。 Apacheなどの一部のWebサーバーはこれを認識し、データをより効率的に提供します。 これは、そのようなサーバーを使用する場合にのみ意味があります。デフォルト:
False
- SEND_FILE_MAX_AGE_DEFAULT
ファイルを提供するときは、キャッシュ制御の最大経過時間をこの秒数に設定します。
datetime.timedelta
またはint
のいずれかになります。 アプリケーションまたはブループリントでget_send_file_max_age()
を使用して、ファイルごとにこの値をオーバーライドします。デフォルト:
timedelta(hours=12)
(43200
秒)
- SERVER_NAME
バインドされているホストとポートをアプリケーションに通知します。 サブドメインルートマッチングのサポートに必要です。
設定されている場合、 SESSION_COOKIE_DOMAIN が設定されていない場合、セッションCookieドメインに使用されます。 最新のWebブラウザーでは、ドットのないドメインにCookieを設定することはできません。 ドメインをローカルで使用するには、アプリにルーティングする必要のある名前を
hosts
ファイルに追加します。127.0.0.1 localhost.dev
設定されている場合、
url_for
は、リクエストコンテキストではなく、アプリケーションコンテキストのみを使用して外部URLを生成できます。デフォルト:
None
- APPLICATION_ROOT
アプリケーション/ Webサーバーによってマウントされているパスをアプリケーションに通知します。
SESSION_COOKIE_PATH
が設定されていない場合、セッションCookieパスに使用されます。デフォルト:
'/'
- PREFERRED_URL_SCHEME
このスキームを使用して、リクエストコンテキストにないときに外部URLを生成します。
デフォルト:
'http'
- MAX_CONTENT_LENGTH
着信要求データからこれ以上のバイトを読み取らないでください。 設定されておらず、リクエストで
CONTENT_LENGTH
が指定されていない場合、セキュリティのためにデータは読み取られません。デフォルト:
None
- JSON_AS_ASCII
オブジェクトをASCIIエンコードされたJSONにシリアル化します。 これが無効になっている場合、JSONはUnicode文字列として返されるか、
jsonify
によってUTF-8
としてエンコードされます。 これは、JSONをテンプレートでJavaScriptにレンダリングするときにセキュリティに影響するため、通常は有効のままにしておく必要があります。デフォルト:
True
- JSON_SORT_KEYS
JSONオブジェクトのキーをアルファベット順に並べ替えます。 これは、Pythonのハッシュシードが何であっても、データが同じ方法でシリアル化されることを保証するため、キャッシュに役立ちます。 推奨されていませんが、これを無効にして、キャッシュを犠牲にしてパフォーマンスを向上させることができます。
デフォルト:
True
- JSONIFY_PRETTYPRINT_REGULAR
jsonify
の応答は、人間が読みやすいように改行、スペース、およびインデントを付けて出力されます。 デバッグモードでは常に有効になります。デフォルト:
False
- JSONIFY_MIMETYPE
jsonify
応答のmimetype。デフォルト:
'application/json'
- TEMPLATES_AUTO_RELOAD
テンプレートが変更されたときにテンプレートをリロードします。 設定されていない場合、デバッグモードで有効になります。
デフォルト:
None
- EXPLAIN_TEMPLATE_LOADING
テンプレートファイルがどのようにロードされたかを追跡するデバッグ情報をログに記録します。 これは、テンプレートがロードされなかった理由、または間違ったファイルがロードされたように見える理由を理解するのに役立ちます。
デフォルト:
False
- MAX_COOKIE_SIZE
- Cookieヘッダーがこのバイト数よりも大きい場合に警告します。 デフォルトは
4093
です。 大きなCookieは、ブラウザによって黙って無視される場合があります。 警告を無効にするには、0
に設定します。
バージョン0.4の新機能: LOGGER_NAME
バージョン0.5の新機能: SERVER_NAME
バージョン0.6の新機能: MAX_CONTENT_LENGTH
バージョン0.7の新機能: PROPAGATE_EXCEPTIONS
、PRESERVE_CONTEXT_ON_EXCEPTION
バージョン0.8の新機能: TRAP_BAD_REQUEST_ERRORS
、TRAP_HTTP_EXCEPTIONS
、APPLICATION_ROOT
、SESSION_COOKIE_DOMAIN
、SESSION_COOKIE_PATH
、 [ X88X]、SESSION_COOKIE_SECURE
バージョン0.9の新機能: PREFERRED_URL_SCHEME
バージョン0.10の新機能: JSON_AS_ASCII
、JSON_SORT_KEYS
、JSONIFY_PRETTYPRINT_REGULAR
バージョン0.11の新機能: SESSION_REFRESH_EACH_REQUEST
、TEMPLATES_AUTO_RELOAD
、LOGGER_HANDLER_POLICY
、EXPLAIN_TEMPLATE_LOADING
バージョン1.0での変更: LOGGER_NAME
およびLOGGER_HANDLER_POLICY
が削除されました。 構成については、 Logging を参照してください。
FLASK_ENV
環境変数を反映するために、 ENV が追加されました。
セッションCookieのSameSite
オプションを制御するために、 SESSION_COOKIE_SAMESITE が追加されました。
Werkzeugからの警告を制御するために MAX_COOKIE_SIZE を追加しました。
ファイルからの構成
構成は、理想的には実際のアプリケーションパッケージの外部にある別のファイルに保存できると、より便利になります。 これにより、さまざまなパッケージ処理ツール( Setuptools を使用したデプロイ)を介してアプリケーションをパッケージ化および配布し、最後に構成ファイルを変更することができます。
したがって、一般的なパターンは次のとおりです。
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
これは、最初に yourapplication.default_settings モジュールから構成をロードし、次に YOURAPPLICATION_SETTINGS
環境変数が指すファイルの内容で値をオーバーライドします。 この環境変数は、サーバーを起動する前に、シェルでexportコマンドを使用してLinuxまたはOSXで設定できます。
$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ python run-app.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader...
Windowsシステムでは、代わりに set ビルトインを使用してください。
>set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
構成ファイル自体は実際のPythonファイルです。 大文字の値のみが、後で実際にconfigオブジェクトに格納されます。 したがって、構成キーには必ず大文字を使用してください。
構成ファイルの例を次に示します。
# Example configuration
DEBUG = False
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'
拡張機能が起動時に構成にアクセスできるように、構成を非常に早い段階でロードするようにしてください。 configオブジェクトには、個々のファイルからロードする他のメソッドもあります。 完全なリファレンスについては、Config
オブジェクトのドキュメントをお読みください。
環境変数からの構成
環境変数を使用して構成ファイルを指すことに加えて、環境から直接構成値を制御することが役立つ(または必要な)場合があります。
LinuxまたはOSXでは、サーバーを起動する前に、シェルでexportコマンドを使用して環境変数を設定できます。
$ export SECRET_KEY='5f352379324c22463451387a0aec5d2f'
$ export MAIL_ENABLED=false
$ python run-app.py
* Running on http://127.0.0.1:5000/
Windowsシステムでは、代わりにset
ビルトインを使用してください。
>set SECRET_KEY='5f352379324c22463451387a0aec5d2f'
このアプローチは簡単に使用できますが、環境変数は文字列であり、Python型に自動的に逆シリアル化されるわけではないことを覚えておくことが重要です。
環境変数を使用する構成ファイルの例を次に示します。
import os
_mail_enabled = os.environ.get("MAIL_ENABLED", default="true")
MAIL_ENABLED = _mail_enabled.lower() in {"1", "t", "true"}
SECRET_KEY = os.environ.get("SECRET_KEY")
if not SECRET_KEY:
raise ValueError("No SECRET_KEY set for Flask application")
空の文字列以外の値は、Pythonではブール値True
値として解釈されることに注意してください。これは、環境がFalse
を意図した値を明示的に設定する場合に注意が必要です。
拡張機能が起動時に構成にアクセスできるように、構成を非常に早い段階でロードするようにしてください。 configオブジェクトには、個々のファイルからロードする他のメソッドもあります。 完全なリファレンスについては、Config
クラスのドキュメントをお読みください。
構成のベストプラクティス
前述のアプローチの欠点は、テストが少し難しくなることです。 一般に、この問題に対する単一の100 % sソリューションはありませんが、そのエクスペリエンスを改善するために覚えておくことができることがいくつかあります。
- 関数でアプリケーションを作成し、ブループリントを登録します。 これにより、さまざまな構成をアタッチしてアプリケーションの複数のインスタンスを作成できるため、単体テストがはるかに簡単になります。 これを使用して、必要に応じて構成を渡すことができます。
- インポート時に構成が必要なコードを記述しないでください。 構成への要求のみのアクセスに制限する場合は、後で必要に応じてオブジェクトを再構成できます。
開発/生産
ほとんどのアプリケーションには、複数の構成が必要です。 本番サーバーと開発中に使用されるサーバーには、少なくとも別々の構成が必要です。 これを処理する最も簡単な方法は、常にロードされ、バージョン管理の一部であるデフォルト構成と、上記の例で説明したように、必要に応じて値をオーバーライドする別の構成を使用することです。
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
次に、別のconfig.py
ファイルを追加し、YOURAPPLICATION_SETTINGS=/path/to/config.py
をエクスポートするだけで完了です。 ただし、別の方法もあります。 たとえば、インポートまたはサブクラス化を使用できます。
Djangoの世界で非常に人気があるのは、ファイルの先頭にfrom yourapplication.default_settings import *
を追加し、手動で変更をオーバーライドすることにより、構成ファイルでインポートを明示的にすることです。 YOURAPPLICATION_MODE
などの環境変数を調べて、本番、開発などに設定し、それに基づいてさまざまなハードコードされたファイルをインポートすることもできます。
興味深いパターンは、構成にクラスと継承を使用することでもあります。
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
このような構成を有効にするには、from_object()
を呼び出す必要があります。
app.config.from_object('configmodule.ProductionConfig')
from_object()
はクラスオブジェクトをインスタンス化しないことに注意してください。 プロパティへのアクセスなど、クラスをインスタンス化する必要がある場合は、from_object()
を呼び出す前にインスタンス化する必要があります。
from configmodule import ProductionConfig
app.config.from_object(ProductionConfig())
# Alternatively, import via string:
from werkzeug.utils import import_string
cfg = import_string('configmodule.ProductionConfig')()
app.config.from_object(cfg)
構成オブジェクトをインスタンス化すると、構成クラスで@property
を使用できるようになります。
class Config(object):
"""Base config, uses staging database server."""
DEBUG = False
TESTING = False
DB_SERVER = '192.168.1.56'
@property
def DATABASE_URI(self): # Note: all caps
return 'mysql://user@{}/foo'.format(self.DB_SERVER)
class ProductionConfig(Config):
"""Uses production database server."""
DB_SERVER = '192.168.19.32'
class DevelopmentConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
class TestingConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
DATABASE_URI = 'sqlite:///:memory:'
さまざまな方法があり、構成ファイルをどのように管理するかはあなた次第です。 ただし、ここに適切な推奨事項のリストがあります。
- バージョン管理でデフォルト構成を保持します。 値をオーバーライドする前に、構成にこのデフォルト構成を設定するか、独自の構成ファイルにインポートしてください。
- 環境変数を使用して、構成を切り替えます。 これはPythonインタープリターの外部から実行でき、コードにまったく触れることなくさまざまな構成をすばやく簡単に切り替えることができるため、開発とデプロイがはるかに簡単になります。 さまざまなプロジェクトで頻繁に作業している場合は、virtualenvをアクティブ化し、開発構成をエクスポートするソーシング用の独自のスクリプトを作成することもできます。
- 本番環境で fabric などのツールを使用して、コードと構成を本番サーバーに個別にプッシュします。 これを行う方法の詳細については、 Deploying with Fabric パターンに進んでください。
インスタンスフォルダ
バージョン0.8の新機能。
Flask0.8ではインスタンスフォルダーが導入されています。 長い間、Flaskは、アプリケーションのフォルダーに関連するパスを直接(Flask.root_path
を介して)参照することを可能にしました。 これは、アプリケーションの横に保存されている構成をロードした開発者の数でもあります。 ただし、残念ながら、これはアプリケーションがパッケージでない場合にのみうまく機能します。その場合、ルートパスはパッケージのコンテンツを参照します。
Flask 0.8で、新しい属性Flask.instance_path
が導入されました。 これは、「インスタンスフォルダ」と呼ばれる新しい概念を指します。 インスタンスフォルダーは、バージョン管理下になく、デプロイメント固有になるように設計されています。 実行時に変更されるものや構成ファイルを削除するのに最適な場所です。
Flaskアプリケーションを作成するときにインスタンスフォルダーのパスを明示的に指定するか、Flaskにインスタンスフォルダーを自動検出させることができます。 明示的な構成の場合は、 instance_path パラメーターを使用します。
app = Flask(__name__, instance_path='/path/to/instance/folder')
このパスは、提供される場合は絶対である必要があることに注意してください。
instance_path パラメーターが指定されていない場合、次のデフォルトの場所が使用されます。
アンインストールされたモジュール:
/myapp.py /instance
アンインストールされたパッケージ:
/myapp /__init__.py /instance
インストールされているモジュールまたはパッケージ:
$PREFIX/lib/python2.X/site-packages/myapp $PREFIX/var/myapp-instance
$PREFIX
は、Pythonインストールのプレフィックスです。 これは、/usr
またはvirtualenvへのパスにすることができます。sys.prefix
の値を出力して、プレフィックスが何に設定されているかを確認できます。
構成オブジェクトは相対ファイル名からの構成ファイルのロードを提供するため、必要に応じて、ファイル名を介したロードをインスタンスパスに相対するように変更できるようにしました。 構成ファイル内の相対パスの動作は、アプリケーションコンストラクターへの instance_relative_config スイッチを介して、「アプリケーションルートに対して相対的」(デフォルト)から「インスタンスフォルダーに対して相対的」に切り替えることができます。
app = Flask(__name__, instance_relative_config=True)
これは、モジュールから構成をプリロードし、インスタンスフォルダー内のファイル(存在する場合)から構成をオーバーライドするようにFlaskを構成する方法の完全な例です。
app = Flask(__name__, instance_relative_config=True)
app.config.from_object('yourapplication.default_settings')
app.config.from_pyfile('application.cfg', silent=True)
インスタンスフォルダへのパスは、Flask.instance_path
を介して見つけることができます。 Flaskには、Flask.open_instance_resource()
を使用してインスタンスフォルダーからファイルを開くためのショートカットも用意されています。
両方の使用例:
filename = os.path.join(app.instance_path, 'application.cfg')
with open(filename) as f:
config = f.read()
# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
config = f.read()