字符串过滤掉所有最邻近的“<”和“>”之间的字符
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
字符串过滤掉所有最邻近的“<”和“>”之间的字符的更多相关文章
- 【编程题目】在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b。
第 17 题(字符串):题目:在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 思路:此题非常容易. 最开始是想开辟一块空间存储每个字符出现的次数. 但转念一想,似乎 ...
- 一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgWasdfasdf",求出现次数最多的那个字母及次数,如有多个重复的则都求出。
主要掌握String中的方法 char[] toCharArray() 将此字符串转换为一个新的字符数组. int indexOf(String str) 返回 ...
- C#返回字符串的字节长度,一个中文算两个字符的代码
如下代码段是关于C#返回字符串的字节长度,一个中文算两个字符的代码. public static int GetLength(string str) { if (str.Length == 0) re ...
- Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列
Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列 前台传来的字符串:'589,321' SELECT*FROM TAB_A T1 WHERE T1.CODE IN ( SEL ...
- 剑指offer-第五章优化时间和空间效率(在字符串中第一次出现切只出现一次的字符)
题目:在字符串中第一次出现切只出现一次的字符 思路:用HashMap来存放对应的char值和该char出现的次数.做一次变量就可以得到第一个只出现一次的字符. Java代码: import java. ...
- 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)
悉Microsoft支持Unicode的方式. 它的主要目的是方便你查询相关的数据类型和函数,以及修正相应的拼写错误. I18nGuy 主页 XenCraft (Unicode 咨询公司) Engli ...
- JS中substring()方法(用于提取字符串中介于两个指定下标之间的字符)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 【leetcode-03】给定一个字符串,请你找出其中不含有重复字符的最长子串的长度
开个新坑,leetcode上面做题目.下面是题目描述: <!-- 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出 ...
- 2016/1/12 第一题 输出 i 出现次数 第二题 用for循环和if条件句去除字符串中空格 第三题不用endwith 实现尾端字符查询
import java.util.Scanner; public class Number { private static Object i; /* *第一题 mingrikejijavabu中字符 ...
随机推荐
- “C++的数组不支持多态”?
先是在微博上看到了个微博和云风的评论,然后我回了“楼主对C的内存管理不了解”. 后来引发了很多人的讨论,大量的人又借机来黑C++,比如: //@Baidu-ThursdayWang:这不就c++弱爆了 ...
- 还没被玩坏的robobrowser(4)——从页面上抓取感兴趣的内容
背景 本节的知识实际上是属于Beautiful Soup的内容. robobrowser支持Beautiful Soup,一般来说通过下面3个方法获取页面上感兴趣的内容 find find_all s ...
- SharePoint 2013 Designer工作流——Parallel Block的应用
参考目录 安装和配置SharePoint 2013 Workflow SharePoint 2013 实现多级审批工作流 在自定义Workflow时,往往会遇到这样场景,某个审批需要被多人查阅,每个查 ...
- logstash 如何处理 mongodb 导出来的 _id value数据。 how to custom fields of logstash by mongo mapreduce exported data.(example format: {_id:"xxx"} , value:{})
input { file { path => "c:\aa.json" start_position => "beginning" #sincedb ...
- idea自动编译
idea修改后台代码自动编译 On 'update' action = Update classes and resources On frame deactivation = Update clas ...
- JavaScript权威指南第02章 词法结构
词法结构 2.1字符集 JavaScript 是Unicode字符集编写,差点儿支持地球上全部的语言. 2.1.1区分大写和小写 javascript是区分大写和小写的语言. 2.1.2 空格.换行符 ...
- git从ssh到提交到github
1.安装 Git 客户端 yum install git 2.打开 Git Bash,开始键入用户信息,和github通讯用的,不能乱写: git config --global user.name ...
- 2.2 Apache Axis2 快速学习手册之 AXIOM 构建 Web Service
和上一篇的POJO 部署相比主要是services.xml 中配置的消息接受处理器类不一样和Java 类中写法不一样. 使用AXIOM构建服务 样例源码路径: C:\Apps\axis2\axis2- ...
- POJ 1200 Crazy Search(字符串简单的hash)
题目:http://poj.org/problem?id=1200 最近看了一个关于hash的问题,不是很明白,于是乎就找了些关于这方面的题目,这道题是一道简单的hash 字符串题目,就先从他入手吧. ...
- vss整合配置连接到Myeclipse中以及中文配置
配置过很久后 再次配置进行记录以免后续备用 1.下载vss插件和安装vss插件 org.vssplugin_1.6.2 解压到myeclipse 安装路径文件夹C:\MyEclipse 8.5\dro ...