diff --git a/CHANGES b/CHANGES index 157e92e3..62bb2004 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,10 @@ Version 0.13 Major release, unreleased +- Make `app.run()` into a noop if a Flask application is run from the + development server on the command line. This avoids some behavior that + was confusing to debug for newcomers. + Version 0.12.1 -------------- diff --git a/flask/app.py b/flask/app.py index 92ee8772..27918d01 100644 --- a/flask/app.py +++ b/flask/app.py @@ -824,6 +824,13 @@ class Flask(_PackageBoundObject): :func:`werkzeug.serving.run_simple` for more information. """ + # Change this into a no-op if the server is invoked from the + # command line. Have a look at cli.py for more information. + if os.environ.get('FLASK_RUN_FROM_CLI_SERVER') == '1': + from .debughelpers import explain_ignored_app_run + explain_ignored_app_run() + return + from werkzeug.serving import run_simple _host = '127.0.0.1' _port = 5000 diff --git a/flask/cli.py b/flask/cli.py index 074ee768..bde5a13b 100644 --- a/flask/cli.py +++ b/flask/cli.py @@ -412,6 +412,13 @@ def run_command(info, host, port, reload, debugger, eager_loading, """ from werkzeug.serving import run_simple + # Set a global flag that indicates that we were invoked from the + # command line interface provided server command. This is detected + # by Flask.run to make the call into a no-op. This is necessary to + # avoid ugly errors when the script that is loaded here also attempts + # to start a server. + os.environ['FLASK_RUN_FROM_CLI_SERVER'] = '1' + debug = get_debug_flag() if reload is None: reload = bool(debug) diff --git a/flask/debughelpers.py b/flask/debughelpers.py index 90710dd3..9e44fe69 100644 --- a/flask/debughelpers.py +++ b/flask/debughelpers.py @@ -8,6 +8,9 @@ :copyright: (c) 2015 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ +import os +from warnings import warn + from ._compat import implements_to_string, text_type from .app import Flask from .blueprints import Blueprint @@ -153,3 +156,12 @@ def explain_template_loading_attempts(app, template, attempts): info.append(' See http://flask.pocoo.org/docs/blueprints/#templates') app.logger.info('\n'.join(info)) + + +def explain_ignored_app_run(): + if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': + warn(Warning('Silently ignoring app.run() because the ' + 'application is run from the flask command line ' + 'executable. Consider putting app.run() behind an ' + 'if __name__ == "__main__" guard to silence this ' + 'warning.'), stacklevel=3)