热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

pythontornado补充(异步非阻塞)

一:正常访问(同一线程中多个请求是同步阻塞状态)我们先访问index,再去访问main,查看情况二:使用future模块,实现异步非阻塞三:在tornado中使用异步IO请求模块四
一:正常访问(同一线程中多个请求是同步阻塞状态)
import tornado.ioloop
import tornado.web
import tornado.websocket
import datetime,time

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("main")class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        time.sleep(10)
        self.write("index")

st ={
    "template_path": "template",#模板路径配置
    "static_path":static,
}

#路由映射   匹配执行,否则404
application = tornado.web.Application([
    ("/main",MainHandler),
    ("/index",IndexHandler),
],**st)

if __name__=="__main__":
    application.listen(8080)

    #io多路复用
    tornado.ioloop.IOLoop.instance().start()

我们先访问index,再去访问main,查看情况

技术分享图片

二:使用future模块,实现异步非阻塞
import tornado.ioloop
import tornado.web
import tornado.websocket
import time
from tornado.concurrent import Future

class MainHandler(tornado.web.RequestHandler):
    def get(self):

        self.write("main")class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        future = Future()
        tornado.ioloop.IOLoop.current().add_timeout(time.time()+5,self.done)    #会在结束后为future中result赋值
        yield future

    def done(self,*args,**kwargs):
        self.write("index")
        self.finish()  #关闭请求连接,必须在回调中完成

st ={
    "template_path": "template",#模板路径配置
    "static_path":static,
}

#路由映射   匹配执行,否则404
application = tornado.web.Application([
    ("/main",MainHandler),
    ("/index",IndexHandler),
],**st)

if __name__=="__main__":
    application.listen(8080)

    #io多路复用
    tornado.ioloop.IOLoop.instance().start()

技术分享图片

技术分享图片

三:在tornado中使用异步IO请求模块
import tornado.ioloop
import tornado.web
import tornado.websocket
import time
from tornado.concurrent import Future
from tornado import httpclient
from tornado import gen

class MainHandler(tornado.web.RequestHandler):
    def get(self):

        self.write("main")

    def post(self, *args, **kwargs):
        pass

class IndexHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        http = httpclient.AsyncHTTPClient()
        yield http.fetch("http://www.google.com",self.done)

    def done(self):
        self.write("index")
        self.finish()

    def post(self, *args, **kwargs):
        pass

st ={
    "template_path": "template",#模板路径配置
    "static_path":static,
}

#路由映射   匹配执行,否则404
application = tornado.web.Application([
    ("/main",MainHandler),
    ("/index",IndexHandler),
],**st)

if __name__=="__main__":
    application.listen(8080)

    #io多路复用
    tornado.ioloop.IOLoop.instance().start()
四:请求间交互,使用future
import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.concurrent import Future
from tornado import gen

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("main")


class IndexHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        future = Future()
        future.add_done_callback(self.done)
        yield future    #由于future中的result中值一直未被赋值,所有客户端一直等待

    def done(self,*args,**kwargs):
        self.write("index")
        self.finish()

st ={
    "template_path": "template",#模板路径配置
    "static_path":static,
}

#路由映射   匹配执行,否则404
application = tornado.web.Application([
    ("/main",MainHandler),
    ("/index",IndexHandler),
],**st)

if __name__=="__main__":
    application.listen(8080)

    #io多路复用
    tornado.ioloop.IOLoop.instance().start()

技术分享图片

 我们可以在另一个请求中去为这个future中result赋值,使当前请求返回

技术分享图片

import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.concurrent import Future
from tornado import gen

future = None

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        global future
        future.set_result(None)  #为Future中result赋值
        self.write("main")


class IndexHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        global future
        future = Future()
        future.add_done_callback(self.done)
        yield future    #由于future中的result中值一直未被赋值,所有客户端一直等待

    def done(self,*args,**kwargs):
        self.write("index")
        self.finish()

st ={
    "template_path": "template",#模板路径配置
    "static_path":static,
}

#路由映射   匹配执行,否则404
application = tornado.web.Application([
    ("/main",MainHandler),
    ("/index",IndexHandler),
],**st)

if __name__=="__main__":
    application.listen(8080)

    #io多路复用
    tornado.ioloop.IOLoop.instance().start()

技术分享图片

 五:自定义web框架(同步)
# coding:utf8
# __author:  Administrator
# date:      2018/6/30 0030
# /usr/bin/env python
import socket
from select import select
import re

class HttpResponse(object):
    """
    封装响应信息
    """
    def __init__(self, cOntent=‘‘):
        self.content = content
        ‘‘‘

        ‘‘‘
        self.status = "HTTP/1.1 200 OK"
        self.headers = {}
        self.COOKIEs = {}

        self.initResponseHeader()

    def changeStatus(self,status_code,status_desc):
        self.status = "HTTP/1.1 %s %s"%(status_code,status_desc)

    def initResponseHeader(self):
        self.headers[Content-Type]=text/html; charset=utf-8
        self.headers[X-Frame-Options]=SAMEORIGIN
        self.headers[X-UA-Compatible]=IE=10
        self.headers[Cache-Control]=private, max-age=10
        self.headers[Vary]=Accept-Encoding
        self.headers[Connection]=keep-alive

    def response(self):
        resp_content = None
        header_list = [self.status,]
        for item in self.headers.items():
            header_list.append("%s: %s"%(item[0],item[1]))

        header_str = "\r\n".join(header_list)
        resp_content = "\r\n\r\n".join([header_str,self.content])
        return bytes(resp_content, encoding=utf-8)

class HttpRequest:
    def __init__(self,content):
        """content:用户传递的请求头信息,字节型"""
        self.content = content
        self.header_bytes = bytes()
        self.body_bytes = bytes()

        self.header_str = ""
        self.body_str = ""

        self.header_dict = {}

        self.method = ""
        self.url = ""
        self.protocol = ""

        self.initialize()
        self.initialize_headers()

    def initialize(self):
        data = self.content.split(b"\r\n\r\n",1)
        if len(data) == 1:  #全是请求头
            self.header_bytes = self.content
        else:   #含有请求头和请求体
            self.header_bytes,self.body_bytes = data
        self.header_str = str(self.header_bytes,encoding="utf-8")
        self.body_str = str(self.body_bytes,encoding="utf-8")

    def initialize_headers(self):
        headers = self.header_str.split("\r\n")
        first_line = headers[0].split(" ")
        if len(first_line) == 3:
            self.method,self.url,self.protocol = first_line
        for line in headers[1:]:
            k_v = line.split(":",1)
            if len(k_v) == 2:
                k,v = k_v
                self.header_dict[k] = v


def main(request):
    return "main"

def index(request):
    return "index"

routers = [
    ("/main/",main),
    (/index/,index),
]

def run():
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((127.0.0.1, 8080))
    sock.listen(128)
    sock.setblocking(False)

    inputs = []
    inputs.append(sock)
    while True:
        rlist, wlist, elist = select(inputs, [], [], 0.05)  # http是单向的,我们只获取请求即可
        for r in rlist:
            if r == sock:  # 有新的请求到来
                conn, addr = sock.accept()
                conn.setblocking(False)
                inputs.append(conn)
            else:  # 客户端请求数据
                data = b""
                # 开始获取请求头
                while True:
                    try:
                        chunk = r.recv(1024)
                        data += chunk
                    except BlockingIOError as e:
                        chunk = None
                    if not chunk:
                        break

                # 处理请求头,请求体
                request = HttpRequest(data)
                #1.获取url
                #2.路由匹配
                #3.执行函数,获取返回值
                #4.将返回值发送
                flag = False
                func = None
                for route in routers:
                    if re.match(route[0],request.url):
                        flag = True
                        func = route[1]
                        break
                if flag:
                    result = func(request)
                    response = HttpResponse(result)
                    r.sendall(response.response())
                else:
                    response = HttpResponse("Not Found")
                    response.changeStatus(404,"Not Page")
                    r.sendall(response.response())
                inputs.remove(r)
                r.close()


if __name__ == "__main__":
    run()

技术分享图片

技术分享图片

 未实现异步非阻塞

 六:完善自定义web框架(异步)
import socket
from select import select
import re,time

class HttpResponse(object):
    """
    封装响应信息
    """
    def __init__(self, cOntent=‘‘):
        self.content = content
        ‘‘‘

        ‘‘‘
        self.status = "HTTP/1.1 200 OK"
        self.headers = {}
        self.COOKIEs = {}

        self.initResponseHeader()

    def changeStatus(self,status_code,status_desc):
        self.status = "HTTP/1.1 %s %s"%(status_code,status_desc)

    def initResponseHeader(self):
        self.headers[Content-Type]=text/html; charset=utf-8
        self.headers[X-Frame-Options]=SAMEORIGIN
        self.headers[X-UA-Compatible]=IE=10
        self.headers[Cache-Control]=private, max-age=10
        self.headers[Vary]=Accept-Encoding
        self.headers[Connection]=keep-alive

    def response(self):
        resp_content = None
        header_list = [self.status,]
        for item in self.headers.items():
            header_list.append("%s: %s"%(item[0],item[1]))

        header_str = "\r\n".join(header_list)
        resp_content = "\r\n\r\n".join([header_str,self.content])
        return bytes(resp_content, encoding=utf-8)

class HttpRequest:
    def __init__(self,content):
        """content:用户传递的请求头信息,字节型"""
        self.content = content
        self.header_bytes = bytes()
        self.body_bytes = bytes()

        self.header_str = ""
        self.body_str = ""

        self.header_dict = {}

        self.method = ""
        self.url = ""
        self.protocol = ""

        self.initialize()
        self.initialize_headers()

    def initialize(self):
        data = self.content.split(b"\r\n\r\n",1)
        if len(data) == 1:  #全是请求头
            self.header_bytes = self.content
        else:   #含有请求头和请求体
            self.header_bytes,self.body_bytes = data
        self.header_str = str(self.header_bytes,encoding="utf-8")
        self.body_str = str(self.body_bytes,encoding="utf-8")

    def initialize_headers(self):
        headers = self.header_str.split("\r\n")
        first_line = headers[0].split(" ")
        if len(first_line) == 3:
            self.method,self.url,self.protocol = first_line
        for line in headers[1:]:
            k_v = line.split(":",1)
            if len(k_v) == 2:
                k,v = k_v
                self.header_dict[k] = v

class Future:
    def __init__(self,timeout):
        self.result = None
        self.timeout = timeout
        self.start = time.time()

    def add_callback_done(self,callback,request):
        self.callback = callback
        self.request = request

    def call(self):
        if self.result == "timeout":  #超时就不要去获取页面数据,直接返回超时
            return "timeout"
        if self.result:  #若是没有超时,去获取回调数据
            return self.callback(self.request)

def callback(request):
    print(request)
    return "async main"

f = None

def main(request):
    global f
    f = Future(10)
    f.add_callback_done(callback,request)  #设置回调
    return f

def index(request):
    return "index"

def stop(request):
    if f:
        f.result = True
    return "stop"

routers = [
    ("/main/",main),
    (/index/,index),
    (/stop/, stop),  #用于向future的result赋值
]

def run():
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((127.0.0.1, 8080))
    sock.listen(128)
    sock.setblocking(False)

    inputs = []
    async_request_dict = {}
    inputs.append(sock)
    while True:
        rlist, wlist, elist = select(inputs, [], [], 0.05)  # http是单向的,我们只获取请求即可
        for r in rlist:
            if r == sock:  # 有新的请求到来
                conn, addr = sock.accept()
                conn.setblocking(False)
                inputs.append(conn)
            else:  # 客户端请求数据
                data = b""
                # 开始获取请求头
                while True:
                    try:
                        chunk = r.recv(1024)
                        data += chunk
                    except BlockingIOError as e:
                        chunk = None
                    if not chunk:
                        break

                # 处理请求头,请求体
                request = HttpRequest(data)
                #1.获取url
                #2.路由匹配
                #3.执行函数,获取返回值
                #4.将返回值发送
                flag = False
                func = None
                for route in routers:
                    if re.match(route[0],request.url):
                        flag = True
                        func = route[1]
                        break
                if flag:
                    result = func(request)
                    if isinstance(result,Future):  #对于future对象,我们另外做异步处理,不阻塞当前操作
                        async_request_dict[r] = result
                        continue
                    response = HttpResponse(result)
                    r.sendall(response.response())
                else:
                    response = HttpResponse("Not Found")
                    response.changeStatus(404,"Not Page")
                    r.sendall(response.response())
                inputs.remove(r)
                r.close()

        for conn in list(async_request_dict.keys()):  #另外对future对象处理
            future = async_request_dict[conn]
            start = future.start
            timeout = future.timeout
            if (start+timeout) <= time.time():  #超时检测
                future.result = "timeout"
            if future.result:
                response = HttpResponse(future.call())  #获取回调数据
                conn.sendall(response.response())
                conn.close()
                del async_request_dict[conn]  #删除字典中这个链接,和下面inputs列表中链接
                inputs.remove(conn)

if __name__ == "__main__":
    run()

 技术分享图片

技术分享图片

 技术分享图片

python---tornado补充(异步非阻塞)


推荐阅读
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
久久影视001
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有