zoukankan      html  css  js  c++  java
  • 转载 Flask中客户端

    文章转载自https://blog.csdn.net/weixin_37923128/article/details/80992645 , 感谢原作者

     

    当客户端向服务器发送一个请求时,服务器会将请求转发给web应用程序,应用程序处理完这个请求后将会返回一个response。在这篇文章我们分析一下flask怎样处理request,又是怎样生成response的,同时我们应该思考,在这个过程中,flask是怎样让url、endpoint、视图函数一一对应的。

    一旦web应用接收到request,flask就会调用Flask类的call函数。在wsgi_app()函数中,我们看到,在调用了full_dispatch_request()函数后,就生成了response(Response类实例)。

     1 class Flask:
     2     def __call__(self, environ, start_response):
     3         return self.wsgi_app(environ, start_response)
     4 
     5     def wsgi_app(self, environ, start_response):
     6         ctx = self.request_context(environ)
     7         error = None
     8         try:
     9             try:
    10                 ctx.push()
    11                 response = self.full_dispatch_request()
    12             except Exception as e:
    13                 error = e
    14                 response = self.handle_exception(e)
    15            except:
    16                error = sys.exc_info()[1]
    17                raise
    18         return response(environ, start_response)
    19     finally:
    20         if self.should_ignore_error(error):
    21             error = None
    22         ctx.auto_pop(error)

    在函数full_dispatch_request中,我们看到了dispatch_request函数,一路寻找下去,在这个函数里找到了view_functions这个字典。这个字典被多个函数在多个函数中出现。

     1 def full_dispatch_request(self):
     2     self.try_trigger_before_first_request_functions()
     3     try:
     4         request_started.send(self)
     5         rv = self.preprocess_request()
     6         if rv is None:
     7             rv = self.dispatch_request()
     8     except Exception as e:
     9         rv = self.handle_user_exception(e)
    10     return self.finalize_request(rv)
    11 
    12 def dispatch_request(self):
    13     req = _request_ctx_stack.top.request
    14     if req.routing_exception is not None:
    15     self.raise_routing_exception(req)
    16     rule = req.url_rule
    17 
    18     if getattr(rule, 'provide_automatic_options', False) 
    19         and req.method == 'OPTIONS':
    20         return self.make_default_options_response()
    21 return self.view_functions[rule.endpoint](**req.view_args)
    22 
    23 self.view_functions = {}

    那这个add_url_rule函数又是在哪里被调用的呢?往下看。

     1 def add_url_rule(self, rule, endpoint=None, view_func=None,provide_automatic_options=None, **options):
     2     if endpoint is None:
     3         endpoint = _endpoint_from_view_func(view_func)
     4         options['endpoint'] = endpoint
     5         methods = options.pop('methods', None)
     6 
     7 # if the methods are not given and the view_func object knows its
     8 # methods we can use that instead. If neither exists, we go with
     9 # a tuple of only ``GET`` as default.
    10     if methods is None:
    11         methods = getattr(view_func, 'methods', None) or ('GET',)
    12     if isinstance(methods, string_types):
    13         raise TypeError('Allowed methods have to be iterables of strings, ''for example: @app.route(..., methods=["POST"])')
    14     methods = set(item.upper() for item in methods)
    15 
    16 # Methods that should always be added
    17     required_methods = set(getattr(view_func, 'required_methods', ()))
    18 
    19 # starting with Flask 0.8 the view_func object can disable and
    20 # force-enable the automatic options handling.
    21     if provide_automatic_options is None:
    22         provide_automatic_options = getattr(view_func,'provide_automatic_options', None)
    23 
    24     if provide_automatic_options is None:
    25         if 'OPTIONS' not in methods:
    26             provide_automatic_options = True
    27             required_methods.add('OPTIONS')
    28         else:
    29             provide_automatic_options = False
    30 
    31         # Add the required methods now.
    32         methods |= required_methods
    33 
    34         rule = self.url_rule_class(rule, methods=methods, **options)
    35         rule.provide_automatic_options = provide_automatic_options
    36 
    37         self.url_map.add(rule)
    38         if view_func is not None:
    39             old_func = self.view_functions.get(endpoint)
    40                 if old_func is not None and old_func != view_func:
    41                     raise AssertionError('View function mapping is overwriting an ''existing endpoint function: %s' % endpoint)
    42             self.view_functions[endpoint] = view_func

    看到这里就应该明白了。在我们写的web应用程序中,往往需要对视图函数添加路由修饰,如:app.route(‘/’)。正是在路由函数中调用了add_url_rule函数,而这个函数负责绑定相应的视图函数、url、以及endpoint。由此,这三个参数建立联系。而后,在程序运行中,当web程序收到请求后,根据请求中的url找到endpoint,再根据endpoint找到视图函数,然后调用视图函数,在视图函数中,会处理那些需要处理的值(return self.view_functionsrule.endpoint)。接下来这个函数的返回值会交给finalize_request()函数处理。

    1 def route(self, rule, **options):
    2     def decorator(f):
    3         endpoint = options.pop('endpoint', None)
    4         self.add_url_rule(rule, endpoint, f, **options)
    5         return f
    6     return decorator

    正是在这个函数里,生成了response。(response是Response类的实例),最终,这个response被返回给客户端,然后显示为页面。

     1 def finalize_request(self, rv, from_error_handler=False):
     2     response = self.make_response(rv)
     3     try:
     4         response = self.process_response(response)
     5         request_finished.send(self, response=response)
     6     except Exception:
     7         if not from_error_handler:
     8         raise
     9             self.logger.exception('Request finalizing failed with an ''error while handling an error')
    10     return response
  • 相关阅读:
    对弈类游戏的人工智能(5)--2048游戏AI的解读
    对弈类游戏的人工智能(4)--游戏AI的落地
    对弈类游戏的人工智能(3)--博弈树优化
    对弈类游戏的人工智能(2)--学习算法
    java.awt.headless 模式
    SpringBoot启动过程分析
    SpringBoot入门之内嵌Tomcat配置
    git tag的用法
    SpringBoot程序远程debug
    SpringBoot入门之分散配置
  • 原文地址:https://www.cnblogs.com/luke20181010/p/10563419.html
Copyright © 2011-2022 走看看