Flask のコンテキストを理解していないと、「RuntimeError: Working outside of application context」や「RuntimeError: Working outside of request context」といったエラーに遭遇する。これらのエラーの原因と対処法を解説する。
よくあるエラー
from flask import Flask, current_app
app = Flask(__name__)
# エラー: アプリケーションコンテキスト外で current_app にアクセス
print(current_app.config['DEBUG'])
このコードを実行すると以下のエラーが発生する。
コンテキストとは
Flask には2種類のコンテキストがある。
| アプリケーションコンテキスト | current_app, g が利用可能になる |
| リクエストコンテキスト | request, session が利用可能になる |
リクエストが来ると Flask は自動的に両方のコンテキストをプッシュする。しかし、リクエスト外(CLI スクリプト、テスト、バックグラウンドタスクなど)ではコンテキストが存在しない。
解決策 1: with app.app_context()
アプリケーションコンテキストを手動でプッシュする。
from flask import Flask, current_app
app = Flask(__name__)
with app.app_context():
print(current_app.config['DEBUG']) # 正常に動作
解決策 2: with app.test_request_context()
リクエストコンテキストも必要な場合はこちらを使う。
with app.test_request_context('/path'):
print(request.path) # '/path'
print(current_app.name) # 正常に動作
よくある落とし穴: デコレータ内でのアクセス
# 危険: インポート時にコンテキストが存在しない
from flask import current_app
DEBUG = current_app.config['DEBUG'] # エラー
代わりに関数内でアクセスする。
def is_debug():
return current_app.config['DEBUG'] # リクエスト処理中に呼ばれるなら OK
Celery などの非同期タスク
バックグラウンドタスク内でコンテキストを使うには、明示的にプッシュする。
from celery import Celery
celery = Celery()
@celery.task
def async_task():
with app.app_context():
# ここで current_app, g を使える
db.session.query(User).all()
コンテキストを理解することで、Flask アプリケーションをリクエストハンドラ以外の場面でも正しく動作させられる。