diff --git a/src/flask/app.py b/src/flask/app.py index 65e95623..360916db 100644 --- a/src/flask/app.py +++ b/src/flask/app.py @@ -10,6 +10,7 @@ from itertools import chain from threading import Lock from types import TracebackType +import click from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableDict from werkzeug.exceptions import Aborter @@ -23,6 +24,7 @@ from werkzeug.routing import MapAdapter from werkzeug.routing import RequestRedirect from werkzeug.routing import RoutingException from werkzeug.routing import Rule +from werkzeug.serving import is_running_from_reloader from werkzeug.urls import url_quote from werkzeug.utils import redirect as _wz_redirect from werkzeug.wrappers import Response as BaseResponse @@ -908,12 +910,18 @@ class Flask(Scaffold): The default port is now picked from the ``SERVER_NAME`` variable. """ - # Change this into a no-op if the server is invoked from the - # command line. Have a look at cli.py for more information. + # Ignore this call so that it doesn't start another server if + # the 'flask run' command is used. if os.environ.get("FLASK_RUN_FROM_CLI") == "true": - from .debughelpers import explain_ignored_app_run + if not is_running_from_reloader(): + click.secho( + " * Ignoring a call to 'app.run()', the server is" + " already being run with the 'flask run' command.\n" + " Only call 'app.run()' in an 'if __name__ ==" + ' "__main__"\' guard.', + fg="red", + ) - explain_ignored_app_run() return if get_load_dotenv(load_dotenv): diff --git a/src/flask/cli.py b/src/flask/cli.py index 77c1e25a..6e0359d9 100644 --- a/src/flask/cli.py +++ b/src/flask/cli.py @@ -11,6 +11,7 @@ from threading import Lock from threading import Thread import click +from werkzeug.serving import is_running_from_reloader from werkzeug.utils import import_string from .globals import current_app @@ -273,7 +274,7 @@ class DispatchingApp: self._bg_loading_exc = None if use_eager_loading is None: - use_eager_loading = os.environ.get("WERKZEUG_RUN_MAIN") != "true" + use_eager_loading = not is_running_from_reloader() if use_eager_loading: self._load_unlocked() @@ -546,12 +547,6 @@ class FlaskGroup(AppGroup): return sorted(rv) def main(self, *args, **kwargs): - # Set a global flag that indicates that we were invoked from the - # command line interface. 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"] = "true" - if get_load_dotenv(self.load_dotenv): load_dotenv() @@ -637,7 +632,7 @@ def show_server_banner(env, debug, app_import_path, eager_loading): """Show extra startup messages the first time the server is run, ignoring the reloader. """ - if os.environ.get("WERKZEUG_RUN_MAIN") == "true": + if is_running_from_reloader(): return if app_import_path is not None: @@ -653,10 +648,10 @@ def show_server_banner(env, debug, app_import_path, eager_loading): if env == "production": click.secho( " WARNING: This is a development server. Do not use it in" - " a production deployment.", + " a production deployment.\n Use a production WSGI server" + " instead.", fg="red", ) - click.secho(" Use a production WSGI server instead.", dim=True) if debug is not None: click.echo(f" * Debug mode: {'on' if debug else 'off'}") diff --git a/src/flask/debughelpers.py b/src/flask/debughelpers.py index 27d378c2..b1e3ce1b 100644 --- a/src/flask/debughelpers.py +++ b/src/flask/debughelpers.py @@ -1,6 +1,4 @@ -import os import typing as t -from warnings import warn from .app import Flask from .blueprints import Blueprint @@ -159,16 +157,3 @@ def explain_template_loading_attempts(app: Flask, template, attempts) -> None: info.append(" See https://flask.palletsprojects.com/blueprints/#templates") app.logger.info("\n".join(info)) - - -def explain_ignored_app_run() -> None: - 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, - )