Flaskアプリケーションの実行方法

March 25, 2020
執筆者

how to run a flask app header

この記事はMiguel Grinbergこちら(英語)で執筆した記事を日本語化したものです。

長い間、Flaskアプリケーションの有名な「Hello, World」というサンプルコードは、7行構成でした。以下は、2017年6月12日のFlask Webサイトのスナップショットです。

old flask website

その後、このサンプルアプリケーションは5行に短縮されました。以下は2017年6月17日の同じページです。

new flask website

ご覧のように、アプリケーションのコア部分は変更ありませんが、アプリケーションサーバーの開始方法が大幅に変更されています。以前のサンプルでは、アプリケーションスクリプト内で単純なapp.run()コールを使用していますが、新しいサンプルではflask runコマンドとFLASK_APP環境変数を使用しています。

その後の数年間でFlask Webサイトのデザインは大きく変わりましたが、この記事を執筆している2020年の段階では、flask runメソッドはフレームワークの公式ドキュメントで最も頻繁に目にします。

現在も、多くのアプリケーションやコードチュートリアルでapp.run()メソッドが使用されています。理由の1つは、Flaskでは古くとも重要なコンテンツが数多く存在しているためです。app.run()が今も便利で使いやすいコマンドとして、広く利用されていることもあります。

この記事では、それぞれのメソッドの長所と短所について解説します。では、本題に入りましょう。

「app.run()」と「flask run」のどちらを使用するべきか?

最初から難しい質問が登場しました。これからFlaskアプリケーションを始める場合、app.run()flask runのどちらを使用するべきでしょうか?

残念ながら、明確な答えはありません。

重要なのは、いずれのメソッドも開発Webサーバーを起動するということです。これはアプリケーション開発時に自社システム内でローカルに使用するサーバーです。本番サーバーでアプリケーションを起動するのであれば、答えは単純です。どちらも使用しません。本番環境で展開する場合は、gunicornuWSGIなど、本番環境用のWebサーバーを使用します。

開発環境では、どちらのメソッドも完全にサポートされるため、お好きな方を使用できます。もちろん、判断材料があれば選択しやすいでしょう。そこで、この2つのメソッドを詳しく見ていきます。

flask runを使用する場合

flask runメソッドは、最新のソリューションであり、Flaskプロジェクトで推奨されています。

flaskコマンドは、Flaskパッケージのインストール時に仮想環境に追加されます。3つのコマンドを使用できます。

(venv) $ flask --help
Usage: flask [OPTIONS] COMMAND [ARGS]...

  A general utility script for Flask applications.

  Provides commands from Flask, extensions, and the application. Loads the
  application defined in the FLASK_APP environment variable, or from a
  wsgi.py file. Setting the FLASK_ENV environment variable to 'development'
  will enable debug mode.

    $ export FLASK_APP=hello.py
    $ export FLASK_ENV=development
    $ flask run

Options:
  --version  Show the flask version
  --help     Show this message and exit.

Commands:
  routes  Show the routes for the app.
  run     Run a development server.
  shell   Run a shell in the app context.

Flaskフレームワークには、コマンドラインインターフェースモジュールが含まれます。このモジュールでは、サードパーティ製のFlask拡張機能を実行できます。また、独自のアプリケーションを実行してカスタムコマンドをインストールし、3つの基本コマンドを補完することにより、Flaskアプリケーション全体を管理できる、非常に高機能で拡張性に優れたシステムを構成できます。

flask runコマンドで難しいのは、Flaskアプリケーションインスタンスをインポートして使用できるように、このコマンドにFlaskアプリケーションインスタンスの場所を認識させることです。

flask runにアプリケーションインスタンスを認識させるには

flask runコマンドにアプリケーションの場所を認識させるには、FLASK_APP環境変数を設定してインスタンスの場所を指定します。この変数は、以下の5つの方法で設定できます。

  • FLASK_APP="module:name": WSGIアプリケーション向けの標準的な設定方法です。アプリケーションインスタンス名がappであり、hello.pyモジュールで定義されている場合は、FLASK_APP="hello:app"と設定します。単純なモジュールの代わりに、より複雑なインポートパスを標準のドット区切り形式で指定することもできます。例えば、FLASK_APP="server.core:app"のようになります。
  • FLASK_APP="module:function()": アプリケーションでアプリケーションファクトリーパターンを使用している場合は、アプリケーション名の代わりにファクトリー関数名で指定できます。Flaskは、その関数をインポートして呼び出し、アプリケーションを作成します。このフォームでは、ファクトリー関数に引数を渡すこともできます。例えば、FLASK_APP="hello:create_app('dev')"のようになります。
  • FLASK_APP=module: アプリケーション名やファクトリー関数なしでインポートパスのみを指定すると、Flaskはモジュールまたはパッケージをインポートし、アプリケーションを自力で探そうとします。最初にappまたはapplicationグローバル変数を探します。どちらも見つからない場合は、モジュール内のすべてのグローバル変数から、Flaskクラスのインスタンスに設定されている変数を探します。それでもアプリケーションが見つからない場合、Flaskはモジュール内でcreate_app()またはmake_app()という名前のアプリケーションファクトリー関数を探します。見つからない場合は、flask runコマンドを終了してエラーを表示します。
  • FLASK_APP=file.py: Pythonファイル内にアプリケーションがある場合は、単にファイル名を設定するだけです。Flaskはそのアプリケーションをインポートし、1つ上のオプションと同じルールを用いてアプリケーションを探します。
  • FLASK_APPが定義されていない場合、Flaskはimport appimport wsgiの実行を試みます。いずれかが成功すると、上の2つのオプションと同じルールを用いて、インポートされたモジュール内でアプリケーションを探します。

ク簡単なテスト用に短いFlaskアプリケーションを組んでいる場合は、そのFlaskアプリケーションインスタンスにappという名前を付けます。そのインスタンスをapp.pyファイルに記述すると、環境変数を気にせずにflask runを実行できます。

サーバーオプションの設定

flask run`コマンドには、サーバーのリスニングIPアドレスおよびポート、SSL認証などを設定するオプションがあります。

(venv) $ flask run --help
Usage: flask run [OPTIONS]

  Run a local development server.

  This server is for development purposes only. It does not provide the
  stability, security, or performance of production WSGI servers.

  The reloader and debugger are enabled by default if FLASK_ENV=development
  or FLASK_DEBUG=1.

Options:
  -h, --host TEXT                 The interface to bind to.
  -p, --port INTEGER              The port to bind to.
  --cert PATH                     Specify a certificate file to use HTTPS.
  --key FILE                      The key file to use when specifying a
                                  certificate.
  --reload / --no-reload          Enable or disable the reloader. By default
                                  the reloader is active if debug is enabled.
  --debugger / --no-debugger      Enable or disable the debugger. By default
                                  the debugger is active if debug is enabled.
  --eager-loading / --lazy-loader
                                  Enable or disable eager loading. By default
                                  eager loading is enabled if the reloader is
                                  disabled.
  --with-threads / --without-threads
                                  Enable or disable multithreading.
  --extra-files PATH              Extra files that trigger a reload on change.
                                  Multiple paths are separated by

Flaskのデバッグモードはオプションでは指定できません。環境内でFLASK_ENV=developmentを介して設定します。

app.run()の使用

flask runコマンドの多くの複雑な操作を見れば、app.run()がいまも多用される理由が分かるはずです。

このメソッドでは、Flaskにアプリケーションインスタンスの場所を認識させる必要はありません。このオブジェクトでrun()メソッドを直接呼び出すためです。環境変数も不要です。

サーバーオプションの設定

app.run()メソッドは複数のオプションをサポートしています。flask runコマンドで指定できるすべてのオプションとともに、以下のオプションも使用できます。

  • host – リッスンするホスト名。
  • port – Webサーバーのポート。
  • debug – デバッグモードの有効または無効を指定します。
  • load_dotenv – 直近の.envおよび.flaskenvファイルを読み込んで環境変数を設定します。
  • use_reloader – モジュールが変更された場合にサーバーでPythonプロセスを自動的に再起動するかどうかを指定します。
  • use_debugger – Werkzeugデバッグシステムを使用するかどうかを指定します。
  • use_evalex – 例外評価機能を有効にするかどうかを指定します。
  • extra_files – リローダーがモジュールとともに監視すべきファイルのリスト。
  • reloader_interval – リローダーの間隔(秒数)。
  • reloader_type – 使用するリローダーのタイプ。
  • threaded – プロセスがリクエストをそれぞれ別のスレッドで処理するかどうかを指定します。
  • processes – 2以上を指定した場合、それを同時プロセス数の上限とし、リクエストをそれぞれ新しいプロセスで処理します。
  • passthrough_errors – Trueに設定すると、エラーキャッチが無効になります。
  • ssl_context – 接続用のSSLコンテキスト。

app.run()の短所

Flaskアプリケーションを開始するにあたり、app.run()の方が便利だと思われる場合は、このメソッドのflask runに対する2つの短所も把握してください。

  • リローダーの堅牢性が低くなります。アプリケーションをインポートできないとrun()メソッドを呼び出せないため、アプリケーションのインポート中に何らかのエラーが発生すると、リローダーが中断して終了します。flask runの場合は、アプリケーションがエラーでインポートできなくても、リローダーはソースファイルの監視を続けます。エラーが修正されると、再びインポートを試みます。
  • app.run()コマンドには、コマンドラインインターフェースがありません。

選べない場合は、両方使用する

実は、2つのメソッドのどちらかに限定する必要はありません。両方同時に使用できます。まず、メインアプリケーションファイルがapp.run()を最後に呼び出すように設定します。

if __name__ == "__main__":
    app.run()

次に、FLASK_APP環境変数がこのファイルを指すよう設定します。例えば、hello.pyというファイルの場合は、以下のようになります。

export FLASK_APP=hello.py

Microsoft Windowsを使用している場合は、以下のようになります。

set FLASK_APP=hello.py

これで、flask runまたはpython hello.pyを介してアプリケーションを起動できます。Flask CLIにフルアクセスできるようになり、必要に応じて独自のスクリプトも実行できるため、利便性が高まります。

この2つのメソッドは問題なく共存できます。

Miguel Grinbergは、TwilioのTechnical Content担当Python Developerです。このブログでは読者の皆様のPythonプロジェクトを紹介します。ぜひ、mgrinberg [at] twilio [dot] comまでご連絡ください。