Flask

overview

背景

Flask以及它所使用的wsgi库werkzeug和模板引擎jinja2都是由Armin Ronacher和他的团队开发的。实际上Armin Ronacher早就开发出来了werkzeug开源库,旨在为框架封装一个良好的底层的API接口,但过了一段时间,Armin发现还是自己来先做一个吧,然后Flask就诞生了。

任务

分析从发起HTTP请求到响应请求之间的流程

涉及源代码文件:

    • Flask源码

      • app.py
    • werkzeug源码
      • serving.py
    • python基本库源码

      • SocketServer.py
      • BaseHTTPServer.py
  • 先来看一个最小的Flask应用:
from flask import Flask
app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run()

显而易见,app.run是核心代码。我们来看一下app.py中相关的代码:

<app.py>
def run(self, host=None, port=None, debug=None, **options):
from werkzeug.serving import run_simple
run_simple(host, port, self, **options) <serving.py>
def run_simple(hostname, port, application, ...,
request_handler=None, static_files=None, ...):
srv = make_server(hostname, port, application, threaded,
processes, request_handler,
passthrough_errors, ssl_context,
fd=fd)
srv.serve_forever() def make_server(host=None, port=None, app=None, threaded=False, processes=1,
request_handler=None, passthrough_errors=False,
ssl_context=None, fd=None):
return BaseWSGIServer(host, port, app, request_handler,
passthrough_errors, ssl_context, fd=fd)

可以看到实际上是make了一个BaseWSGIServer,这个server开始监听连接。下边来研究一下这个BaseWSGIServer。
BaseWSGIServer继承自python基本库BaseHTTPServer.py中的HTTPServer, HTTPServer继承自SocketServer.py中的TCPServer。

<serving.py>
class BaseWSGIServer(HTTPServer, object):
def __init__(self, host, port, app, handler=None, ...):
if handler is None:
handler = WSGIRequestHandler
HTTPServer.__init__(self, (host, int(port)), handler)
self.app = app class HTTPServer(SocketServer.TCPServer):
def server_bind(self):
.... class TCPServer(BaseServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise <SocketServer.py>
class BaseServer:
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False def serve_forever(self, poll_interval=0.5):
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set() def finish_request(self, request, client_address):
# 这里非常重要,就是实例化请求处理类
self.RequestHandlerClass(request, client_address, self)

从这些代码可以看出,HTTP建立于TCP之上。BaseServer最需要注意的是在构造的时候设置了请求处理类RequestHandlerClass。也就是在BaseWSGIServer构造的时候设置了请求处理类。根据上边的了解,我们知道在app.run()的时候就把请求处理类设置好了,注意这里只是设置了请求处理类,并没有真正的去构建一个处理实例。那么它是在什么时候实例化呢?实际上它是在http请求真正到来的时候才会被实例化。随后我们会继续通过代码看到这个请求处理类在实例化的时候就会自动去处理这个请求。
我们先来简单说一下一个请求的基本处理逻辑。

1.首先一个连接进来,BaseServer监听到连接,调用self._handle_request_noblock()处理
2.self._handle_request_noblock()最终找到finish_request方法
3.finish_request方法实例化请求处理类RequestHandlerClass
BaseWSGIServer的构造函数中,我们看到如果我们不自己实现请求处理句柄的话,就会使用werkzeug库提供的WSGIRequestHandler。我们再来看一下这个类到底是一个什么东西。

<serving.py>
class WSGIRequestHandler(BaseHTTPRequestHandler, object):
def handle(self):
rv = BaseHTTPRequestHandler.handle(self)
return rv
def handle_one_request(self):
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
elif self.parse_request(): # 从tcp到http中间的处理逻辑
return self.run_wsgi() # 真正的处理,随后我们会拿出来研究一下
def run_wsgi(self):
pass <BaseHTTPServer.py>
class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
def parse_request(self):
...
def handle(self):
self.handle_one_request() <SocketServer.py>
class StreamRequestHandler(BaseRequestHandler):
def setup(self):
...
def finish(self):
... class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server # 这个非常重要,设置了request的server,我们随后会看到
self.setup()
try:
self.handle()
finally:
self.finish()

一层一层的继承下来,实际上就是继承的python基本库里的基本请求处理类。这个类在实例化的时候会调用handle函数处理,handle函数我们在WSGIRequestHandler中复写了,handle函数会调用我们在WSGIRequestHandler中复写的handle_one_request函数。好了,终于找到头了。我们看一下这个run_wsgi是怎么处理的。函数稍微长一些,我们拣逻辑性的重要代码分析一下。

def run_wsgi(self):
def write(data):
...
self.wfile.write(data) # 回复响应数据
def start_response(status, response_headers, exc_info=None):
...
return write
def execute(app):
application_iter = app(environ, start_response)
for data in application_iter:
write(data)
execute(self.server.app)

代码很清楚,就是调用了app来处理请求,然后app匹配url找到视图view,真正的处理。你说app是怎么来的?我们上边研究过了,它是在请求到来的时候,由server传递给请求处理类的。也就是说只有当请求连接的时候,才会实例化处理类,处理类在实例化的时候就会配置它的server。就是下边的代码。

 <SocketServer.py>
class BaseServer:
def finish_request(self, request, client_address):
# 这里非常重要,就是实例化请求处理类
self.RequestHandlerClass(request, client_address, self) class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.server = server <serving.py>
class BaseWSGIServer(HTTPServer, object):
def __init__(self, host, port, app, handler=None, ...):
self.app = app

好了,以上的流程我们都清楚了。下边就开始研究app(environ, start_response)的奇妙了。

https://blog.csdn.net/u010007589/article/details/70338066

https://blog.csdn.net/u010007589/article/details/50542251

字符串过滤掉所有最邻近的“<”和“>”之间的字符的更多相关文章

  1. 【编程题目】在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b。

    第 17 题(字符串):题目:在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 思路:此题非常容易. 最开始是想开辟一块空间存储每个字符出现的次数. 但转念一想,似乎 ...

  2. 一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgWasdfasdf",求出现次数最多的那个字母及次数,如有多个重复的则都求出。

    主要掌握String中的方法 char[] toCharArray()           将此字符串转换为一个新的字符数组. int indexOf(String str)           返回 ...

  3. C#返回字符串的字节长度,一个中文算两个字符的代码

    如下代码段是关于C#返回字符串的字节长度,一个中文算两个字符的代码. public static int GetLength(string str) { if (str.Length == 0) re ...

  4. Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列

    Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列   前台传来的字符串:'589,321' SELECT*FROM TAB_A T1 WHERE  T1.CODE  IN ( SEL ...

  5. 剑指offer-第五章优化时间和空间效率(在字符串中第一次出现切只出现一次的字符)

    题目:在字符串中第一次出现切只出现一次的字符 思路:用HashMap来存放对应的char值和该char出现的次数.做一次变量就可以得到第一个只出现一次的字符. Java代码: import java. ...

  6. 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)

    悉Microsoft支持Unicode的方式. 它的主要目的是方便你查询相关的数据类型和函数,以及修正相应的拼写错误. I18nGuy 主页 XenCraft (Unicode 咨询公司) Engli ...

  7. JS中substring()方法(用于提取字符串中介于两个指定下标之间的字符)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 【leetcode-03】给定一个字符串,请你找出其中不含有重复字符的最长子串的长度

    开个新坑,leetcode上面做题目.下面是题目描述: <!-- 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出 ...

  9. 2016/1/12 第一题 输出 i 出现次数 第二题 用for循环和if条件句去除字符串中空格 第三题不用endwith 实现尾端字符查询

    import java.util.Scanner; public class Number { private static Object i; /* *第一题 mingrikejijavabu中字符 ...

随机推荐

  1. java 获取局域网中的全部主机名和IP地址

    DOS命令 命令 意义 net view 获取局域网中的全部主机名 ipconfig -all 获取本地IP,主机名,MAC地址 arp -a 获取本局域网中的全部IP地址和物理地址 ping -a ...

  2. 最烂编程语言得主:javascript

    C++在我脑中一直是一门缺乏设计和远见的语言,其设计者也是缺少主见的人(我承认我对c++有一定偏见),在我看来,C++从一开始就是堆叠语言特性,成为最流行的语言,,只是这个时代将它推到了最前列,我心中 ...

  3. stm8 I/O口模式配置

    复位后的默认配置 :复位之后,所有的引脚都是悬浮输入模式. However, a few pins may have a different behavior. Refer to the datash ...

  4. 【转载并整理】mysql 创建用户,数据库

    http://www.jb51.net/article/31850.htm https://www.cnblogs.com/SQL888/p/5748824.html http://www.cnblo ...

  5. 大家来找茬:富连网今天中午抢购二手iPhone时网站无法访问的问题

    前几天在新闻区看到富士康卖二手iPhone的新闻,今天又看到说今天中午12点开抢.一大早就发现富连网无法访问了.前几天刚看到新闻的时候注册了个账号进去看了看,发现页面加载速度非常慢,今天中午基本无法打 ...

  6. 在linux中配置环境变量

    JDK下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 根据Linux ...

  7. 关于 sql server 数据库权限乱七八糟的一些东西

    研究权限这些东西主要是因为今天正好在折腾数据库备份相关的东西,备份好说,备份完了就完了. 但是恢复备份的时候,需要先让数据库脱机,然后恢复,然后再联机,嗯,问题就出在联机上了. 根据 MSDN 的说法 ...

  8. Linux 索引节点(inode)详解

    参考文章:http://www.ruanyifeng.com/blog/2011/12/inode.html

  9. lua -- table.nums

    table.nums 计算表格包含的字段数量. 格式: count = table.nums(表格对象) Lua 的“#”操作可以取得表格的长度,但仅限从 开始连续数字为索引的表格.table.num ...

  10. DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

    [概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天 ...