forked from orbit-oss/flask
Merge pull request #3434 from pallets/eager-load
lazy load app on reload only
This commit is contained in:
commit
bfa9aceb03
4 changed files with 72 additions and 41 deletions
|
|
@ -10,6 +10,9 @@ Unreleased
|
||||||
- Add :meth:`Config.from_file` to load config using arbitrary file
|
- Add :meth:`Config.from_file` to load config using arbitrary file
|
||||||
loaders, such as ``toml.load`` or ``json.load``.
|
loaders, such as ``toml.load`` or ``json.load``.
|
||||||
:meth:`Config.from_json` is deprecated in favor of this. :pr:`3398`
|
:meth:`Config.from_json` is deprecated in favor of this. :pr:`3398`
|
||||||
|
- The ``flask run`` command will only defer errors on reload. Errors
|
||||||
|
present during the initial call will cause the server to exit with
|
||||||
|
the traceback immediately. :issue:`3431`
|
||||||
|
|
||||||
|
|
||||||
Version 1.1.2
|
Version 1.1.2
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,8 @@ Old Version of Flask
|
||||||
Versions of Flask older than 0.11 use to have different ways to start the
|
Versions of Flask older than 0.11 use to have different ways to start the
|
||||||
application. In short, the :command:`flask` command did not exist, and
|
application. In short, the :command:`flask` command did not exist, and
|
||||||
neither did :command:`python -m flask`. In that case you have two options:
|
neither did :command:`python -m flask`. In that case you have two options:
|
||||||
either upgrade to newer Flask versions or have a look at the :ref:`server`
|
either upgrade to newer Flask versions or have a look at :doc:`/server`
|
||||||
docs to see the alternative method for running a server.
|
to see the alternative method for running a server.
|
||||||
|
|
||||||
Invalid Import Name
|
Invalid Import Name
|
||||||
```````````````````
|
```````````````````
|
||||||
|
|
@ -153,7 +153,7 @@ This does the following things:
|
||||||
You can also control debug mode separately from the environment by
|
You can also control debug mode separately from the environment by
|
||||||
exporting ``FLASK_DEBUG=1``.
|
exporting ``FLASK_DEBUG=1``.
|
||||||
|
|
||||||
There are more parameters that are explained in the :ref:`server` docs.
|
There are more parameters that are explained in :doc:`/server`.
|
||||||
|
|
||||||
.. admonition:: Attention
|
.. admonition:: Attention
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,89 @@
|
||||||
.. _server:
|
.. currentmodule:: flask
|
||||||
|
|
||||||
Development Server
|
Development Server
|
||||||
==================
|
==================
|
||||||
|
|
||||||
.. currentmodule:: flask
|
Flask provides a ``run`` command to run the application with a
|
||||||
|
development server. In development mode, this server provides an
|
||||||
|
interactive debugger and will reload when code is changed.
|
||||||
|
|
||||||
Starting with Flask 0.11 there are multiple built-in ways to run a
|
.. warning::
|
||||||
development server. The best one is the :command:`flask` command line utility
|
|
||||||
but you can also continue using the :meth:`Flask.run` method.
|
Do not use the development server when deploying to production. It
|
||||||
|
is intended for use only during local development. It is not
|
||||||
|
designed to be particularly efficient, stable, or secure.
|
||||||
|
|
||||||
|
See :doc:`/deploying/index` for deployment options.
|
||||||
|
|
||||||
Command Line
|
Command Line
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The :command:`flask` command line script (:ref:`cli`) is strongly
|
The ``flask run`` command line script is the recommended way to run the
|
||||||
recommended for development because it provides a superior reload
|
development server. It requires setting the ``FLASK_APP`` environment
|
||||||
experience due to how it loads the application. The basic usage is like
|
variable to point to your application, and ``FLASK_ENV=development`` to
|
||||||
this::
|
fully enable development mode.
|
||||||
|
|
||||||
$ export FLASK_APP=my_application
|
.. code-block:: text
|
||||||
|
|
||||||
|
$ export FLASK_APP=hello
|
||||||
$ export FLASK_ENV=development
|
$ export FLASK_ENV=development
|
||||||
$ flask run
|
$ flask run
|
||||||
|
|
||||||
This enables the development environment, including the interactive
|
This enables the development environment, including the interactive
|
||||||
debugger and reloader, and then starts the server on
|
debugger and reloader, and then starts the server on
|
||||||
*http://localhost:5000/*.
|
http://localhost:5000/. Use ``flask run --help`` to see the available
|
||||||
|
options, and :doc:`/cli` for detailed instructions about configuring
|
||||||
The individual features of the server can be controlled by passing more
|
and using the CLI.
|
||||||
arguments to the ``run`` option. For instance the reloader can be
|
|
||||||
disabled::
|
|
||||||
|
|
||||||
$ flask run --no-reload
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Prior to Flask 1.0 the :envvar:`FLASK_ENV` environment variable was
|
Prior to Flask 1.0 the ``FLASK_ENV`` environment variable was not
|
||||||
not supported and you needed to enable debug mode by exporting
|
supported and you needed to enable debug mode by exporting
|
||||||
``FLASK_DEBUG=1``. This can still be used to control debug mode, but
|
``FLASK_DEBUG=1``. This can still be used to control debug mode, but
|
||||||
you should prefer setting the development environment as shown
|
you should prefer setting the development environment as shown
|
||||||
above.
|
above.
|
||||||
|
|
||||||
|
|
||||||
|
Lazy or Eager Loading
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
When using the ``flask run`` command with the reloader, the server will
|
||||||
|
continue to run even if you introduce syntax errors or other
|
||||||
|
initialization errors into the code. Accessing the site will show the
|
||||||
|
interactive debugger for the error, rather than crashing the server.
|
||||||
|
This feature is called "lazy loading".
|
||||||
|
|
||||||
|
If a syntax error is already present when calling ``flask run``, it will
|
||||||
|
fail immediately and show the traceback rather than waiting until the
|
||||||
|
site is accessed. This is intended to make errors more visible initially
|
||||||
|
while still allowing the server to handle errors on reload.
|
||||||
|
|
||||||
|
To override this behavior and always fail immediately, even on reload,
|
||||||
|
pass the ``--eager-loading`` option. To always keep the server running,
|
||||||
|
even on the initial call, pass ``--lazy-loading``.
|
||||||
|
|
||||||
|
|
||||||
In Code
|
In Code
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The alternative way to start the application is through the
|
As an alternative to the ``flask run`` command, the development server
|
||||||
:meth:`Flask.run` method. This will immediately launch a local server
|
can also be started from Python with the :meth:`Flask.run` method. This
|
||||||
exactly the same way the :command:`flask` script does.
|
method takes arguments similar to the CLI options to control the server.
|
||||||
|
The main difference from the CLI command is that the server will crash
|
||||||
|
if there are errors when reloading.
|
||||||
|
|
||||||
Example::
|
``debug=True`` can be passed to enable the debugger and reloader, but
|
||||||
|
the ``FLASK_ENV=development`` environment variable is still required to
|
||||||
|
fully enable development mode.
|
||||||
|
|
||||||
if __name__ == '__main__':
|
Place the call in a main block, otherwise it will interfere when trying
|
||||||
app.run()
|
to import and run the application with a production server later.
|
||||||
|
|
||||||
This works well for the common case but it does not work well for
|
.. code-block:: python
|
||||||
development which is why from Flask 0.11 onwards the :command:`flask`
|
|
||||||
method is recommended. The reason for this is that due to how the reload
|
|
||||||
mechanism works there are some bizarre side-effects (like executing
|
|
||||||
certain code twice, sometimes crashing without message or dying when a
|
|
||||||
syntax or import error happens).
|
|
||||||
|
|
||||||
It is however still a perfectly valid method for invoking a non automatic
|
if __name__ == "__main__":
|
||||||
reloading application.
|
app.run(debug=True)
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
$ python hello.py
|
||||||
|
|
|
||||||
|
|
@ -296,11 +296,15 @@ class DispatchingApp(object):
|
||||||
of the Werkzeug debugger means that it shows up in the browser.
|
of the Werkzeug debugger means that it shows up in the browser.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, loader, use_eager_loading=False):
|
def __init__(self, loader, use_eager_loading=None):
|
||||||
self.loader = loader
|
self.loader = loader
|
||||||
self._app = None
|
self._app = None
|
||||||
self._lock = Lock()
|
self._lock = Lock()
|
||||||
self._bg_loading_exc_info = None
|
self._bg_loading_exc_info = None
|
||||||
|
|
||||||
|
if use_eager_loading is None:
|
||||||
|
use_eager_loading = os.environ.get("WERKZEUG_RUN_MAIN") != "true"
|
||||||
|
|
||||||
if use_eager_loading:
|
if use_eager_loading:
|
||||||
self._load_unlocked()
|
self._load_unlocked()
|
||||||
else:
|
else:
|
||||||
|
|
@ -802,7 +806,7 @@ class SeparatedPathType(click.Path):
|
||||||
"is active if debug is enabled.",
|
"is active if debug is enabled.",
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--eager-loading/--lazy-loader",
|
"--eager-loading/--lazy-loading",
|
||||||
default=None,
|
default=None,
|
||||||
help="Enable or disable eager loading. By default eager "
|
help="Enable or disable eager loading. By default eager "
|
||||||
"loading is enabled if the reloader is disabled.",
|
"loading is enabled if the reloader is disabled.",
|
||||||
|
|
@ -841,9 +845,6 @@ def run_command(
|
||||||
if debugger is None:
|
if debugger is None:
|
||||||
debugger = debug
|
debugger = debug
|
||||||
|
|
||||||
if eager_loading is None:
|
|
||||||
eager_loading = not reload
|
|
||||||
|
|
||||||
show_server_banner(get_env(), debug, info.app_import_path, eager_loading)
|
show_server_banner(get_env(), debug, info.app_import_path, eager_loading)
|
||||||
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
|
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue