flask运行源码
- flask源码app.py实现
...
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
"""Runs the application on a local development server.
Do not use ``run()`` in a production setting. It is not intended to
meet security and performance requirements for a production server.
Instead, see :ref:`deployment` for WSGI server recommendations.
If the :attr:`debug` flag is set the server will automatically reload
for code changes and show a debugger in case an exception happened.
If you want to run the application in debug mode, but disable the
code execution on the interactive debugger, you can pass
``use_evalex=False`` as parameter. This will keep the debugger's
traceback screen active, but disable code execution.
It is not recommended to use this function for development with
automatic reloading as this is badly supported. Instead you should
be using the :command:`flask` command line script's ``run`` support.
.. admonition:: Keep in Mind
Flask will suppress any server error with a generic error page
unless it is in debug mode. As such to enable just the
interactive debugger without the code reloading, you have to
invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``.
Setting ``use_debugger`` to ``True`` without being in debug mode
won't catch any exceptions because there won't be any to
catch.
:param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
have the server available externally as well. Defaults to
``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable
if present.
:param port: the port of the webserver. Defaults to ``5000`` or the
port defined in the ``SERVER_NAME`` config variable if present.
:param debug: if given, enable or disable debug mode. See
:attr:`debug`.
:param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv`
files to set environment variables. Will also change the working
directory to the directory containing the first file found.
:param options: the options to be forwarded to the underlying Werkzeug
server. See :func:`werkzeug.serving.run_simple` for more
information.
.. versionchanged:: 1.0
If installed, python-dotenv will be used to load environment
variables from :file:`.env` and :file:`.flaskenv` files.
If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG`
environment variables will override :attr:`env` and
:attr:`debug`.
Threaded mode is enabled by default.
.. versionchanged:: 0.10
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.
if os.environ.get("FLASK_RUN_FROM_CLI") == "true":
from .debughelpers import explain_ignored_app_run
explain_ignored_app_run()
return
if get_load_dotenv(load_dotenv):
cli.load_dotenv()
# if set, let env vars override previous values
if "FLASK_ENV" in os.environ:
self.env = get_env()
self.debug = get_debug_flag()
elif "FLASK_DEBUG" in os.environ:
self.debug = get_debug_flag()
# debug passed to method overrides all other sources
if debug is not None:
self.debug = bool(debug)
_host = "127.0.0.1"
_port = 5000
server_name = self.config.get("SERVER_NAME")
sn_host, sn_port = None, None
if server_name:
sn_host, _, sn_port = server_name.partition(":")
host = host or sn_host or _host
# pick the first value that's not None (0 is allowed)
port = int(next((p for p in (port, sn_port) if p is not None), _port))
options.setdefault("use_reloader", self.debug)
options.setdefault("use_debugger", self.debug)
options.setdefault("threaded", True)
cli.show_server_banner(self.env, self.debug, self.name, False)
from werkzeug.serving import run_simple
try:
run_simple(host, port, self, **options)
finally:
# reset the first request information if the development server
# reset normally. This makes it possible to restart the server
# without reloader and that stuff from an interactive shell.
self._got_first_request = False
...
def wsgi_app(self, environ, start_response):
"""The actual WSGI application. This is not implemented in
:meth:`__call__` so that middlewares can be applied without
losing a reference to the app object. Instead of doing this::
app = MyMiddleware(app)
It's a better idea to do this instead::
app.wsgi_app = MyMiddleware(app.wsgi_app)
Then you still have the original application object around and
can continue to call methods on it.
.. versionchanged:: 0.7
Teardown events for the request and app contexts are called
even if an unhandled error occurs. Other events may not be
called depending on when an error occurs during dispatch.
See :ref:`callbacks-and-errors`.
:param environ: A WSGI environment.
:param start_response: A callable accepting a status code,
a list of headers, and an optional exception context to
start the response.
"""
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except: # noqa: B001
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
...
- 阅读源码,可以看出代码运行顺序是:
- 启动
app.run()
—>run_simple(host, port, self...)
—>make_server(hostname,port,application,threaded,processes...)
—>ThreadedWSGIServer(BaseWSGIServer(host, port, app...))
—>
5.WSGIRequestHandler(BaseHTTPRequestHandler, object)
—>
- 请求处理
run_wsgi
-->app(environ, start_response)
,即调用Flask()的__call__方法式__call__
- 调用
wsgi_app
函数
3.1RequestContext
= Request(environ)
3.2app.request_class(environ)和ctx.push
…
3.3auto_pop
flask请求处理
四大上下文变量
- 四大变量脱离请求后无法访问
from flask import Flask,current_app,request,g,session
app = Flask(__name__)
print(current_app) # RuntimeError: Working outside of application context.
print(g) # RuntimeError: Working outside of application context.
print(session) # RuntimeError: Working outside of request context.
print(request) # RuntimeError: Working outside of request context.
- 四大变量在请求中可以访问,表明需要上下文环境
from flask import Flask,current_app,request,g,session
app = Flask(__name__)
@app.route('/')
def index():
print(current_app) # <Flask 'demo'>
print(g) # <flask.g of 'demo'>
print(session) # <NullSession {}>
print(request) # <Request 'http://127.0.0.1:5000/' [GET]>
return 'Hello'
if __name__ == '__main__':
app.run(debug=True)
- 外部环境依赖解决思路:
- 参照上例请求传参
- 全局变量传参,如下
request = {
'username':'zhangsan','pwd':'123456','age': 18}
@app.route('/')
def index():
return request.get('username')
- 假设有多个用户访问,此时就会有多个线程,username变量就会混乱。此时可以采用[{},{}…]存储,但由于列表是无须的,所以还是可能混乱。flask采用将数据绑定到线程上,保证数据不会混乱。
request = {
'线程_id':
{
'username':'zhangsan','pwd':'123456','age': 18}
}
@app.route('/')
def index():
return request.get('username')
flask上下文处理
参考文档
https://blog.csdn.net/m0_37519490/article/details/80704717
https://www.h5w3.com/13717.html
flask线程隔离
参考文档
https://blog.csdn.net/weixin_41207499/article/details/80724826
https://blog.csdn.net/weixin_43116723/article/details/107994241