How to run Flask app by flask run or custom command without set FLASK_APP manually

ewels picture ewels · Mar 20, 2019 · Viewed 7.5k times · Source

Use case

I have a python package using a click group to have multiple command line subcommands. In addition to this, I would like to have a small flask application.

The other subcommands are the primary function of the package - not the flask application. As such, I would like the flask commands to be nested under their own group.

Example

I made a minimal example to demonstrate my problem - it's on GitHub here: https://github.com/ewels/flask-subcommand-issue

What works

In the minimal example, I set up a mini flask installation that runs with the fsksc_server command. This is thanks to a setuptools console_scripts entry point hook in setup.py.

The command works perfectly, exactly as you would expect:

$ fsksc_server --help

Usage: fsksc_server [OPTIONS] COMMAND [ARGS]...

  Run the fsksc server flask app

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

Commands:
  routes  Show the routes for the app.
  run     Runs a development server.
  shell   Runs a shell in the app context.
$ fsksc_server run

 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

(I haven't set up any routes, so visiting the URL throws a 404, but the server is running fine..)

To get the flask commands in a click subcommand I have used flask add_command with the flask group. This main command is fsksc. The flask subcommand should be shell. The intention is to make fsksc shell run launch the development server.

The commands show up properly, so this part seems to work:

$ fsksc --help

Usage: fsksc [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  cmd1
  cmd2
  server  Run the fsksc server flask app

What doesn't work

When doing anything under the server subcommand, I get a warning message about a NoAppException exception:

$ fsksc server --help

Traceback (most recent call last):
  File "/Users/ewels/miniconda2/envs/work/lib/python2.7/site-packages/Flask-1.0.2-py2.7.egg/flask/cli.py", line 529, in list_commands
    rv.update(info.load_app().cli.list_commands(ctx))
  File "/Users/ewels/miniconda2/envs/work/lib/python2.7/site-packages/Flask-1.0.2-py2.7.egg/flask/cli.py", line 384, in load_app
    'Could not locate a Flask application. You did not provide '
NoAppException: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the current directory.
Usage: fsksc server [OPTIONS] COMMAND [ARGS]...

  Run the fsksc server flask app

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

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

Trying to run the server gives a similar error:

$ fsksc server run

 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
Usage: fsksc server run [OPTIONS]

Error: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the current directory.

Crappy workaround

I can fix this by defining the FLASK_APP environment variable correctly. Then flask run works as expected:

$ export FLASK_APP=/Users/ewels/GitHub/flask-subcommand-issue/fsksc/server/app.py:create_fsksc_app

$ fsksc server run

 * Serving Flask app "/Users/ewels/GitHub/flask-subcommand-issue/fsksc/server/app.py:create_fsksc_app"
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

flask run also works.

But - I don't want to have to get my users to do this! I also don't want to pollute my main command group with the flask subcommands (in reality I have a lot more subcommands in the main group).

The question

What do I need to do to make this work as I intend, without having to define FLASK_APP and as a nested group in click?

Thank you in advance for any help!

Answer

Grey Li picture Grey Li · Mar 21, 2019

Create a file named .flaskenv under the root of your project, put this content into it:

FLASK_APP=fsksc.server.app:create_fsksc_app

then install python-dotenv:

$ pip install python-dotenv

Now the env var should be set automatically when you excute your run command.