Tornado提升之同步与异步

同步与异步

同步
  • 按部就班的依次执行代码
异步
  • 概述:对于耗时的操作交给别人(另一个线程)去处理,我们继续向下去执行,
    当别人结束耗时操作后再将结果反馈给我们

  • 回调函数实现异步

    import time
    import threading
    
    
    def longIo(callback):
    
    def run(cb):
        print("开始耗时操作")
        time.sleep(5)
        print("结束耗时操作")
        # 执行回调函数
        cb("luciano is good man")
    
    threading.Thread(target=run,args=(callback,)).start()
    
    # 回调函数
    def finish(data):
        print("开始处理回调函数")
        print("接收到longIO的数据:",data)
        print("结束处理回调函数")
    
    # 两个客户端的请求s
    def reqA():
        print("开始处理reqA")
        longIo(finish)
        print("结束处理reqA")
    def reqB():
        print("开始处理reqB")
        time.sleep(2)
        print("结束处理reqB")
    
    # tornado服务
    def main():
        reqA()
        reqB()
        while True:
            time.sleep(0.5)
    
    if __name__ == '__main__':
        main()
    
  • 协程实现异步

    版本1:
    协程
    
       import time
       import threading
       
       gen = None
       
       
       def longIo():
       
           def run():
               print("开始耗时操作")
               time.sleep(5)
               try:
       
                   global gen
                   gen.send("luciano is good man")
               except StopIteration:
                   pass
               print("结束耗时操作")
       
       
       
           threading.Thread(target=run).start()
       
       
       
       
       # 两个客户端的请求s
       def reqA():
           print("开始处理reqA")
       
           res = yield longIo()
           print("接收到longIO的数据:", res)
       
           print("结束处理reqA")
       def reqB():
           print("开始处理reqB")
           time.sleep(2)
           print("结束处理reqB")
       
       # tornado服务
       
       
           def main():
           
               # 创建生成器
               global gen
               gen=reqA()
               next(gen) # next()开启,查找yield执行
           
               reqB()
               while True:
                   time.sleep(0.5)
           
           if __name__ == '__main__':
               main()
               ```
    问题:版本1 中再调用reqA的时候不能将其视为一个简单的函数,而是需要作为生成器使用
    
    - 版本2
       
                   # 协程
           import time
           import threading
           
           gen = None
           
           
           def longIo():
           
               def run():
                   print("开始耗时操作")
                   time.sleep(5)
                   try:
                       global gen
                       gen.send("luciano is good man")
                   except StopIteration:
                       pass
                   print("结束耗时操作")
               threading.Thread(target=run).start()
           
           
           def genCoroutine(func):
               def wrapper(*args,**kwargs):
                   global gen
                   gen = func(*args,**kwargs)
                   next(gen)
               return wrapper
           
           
           @genCoroutine
           # 两个客户端的请求s
           def reqA():
               print("开始处理reqA")
               res = yield longIo()
               print("接收到longIO的数据:", res)
           
               print("结束处理reqA")
           def reqB():
               print("开始处理reqB")
               time.sleep(2)
               print("结束处理reqB")
           
           # tornado服务
           def main():
               reqA()
               reqB()
               while True:
                   time.sleep(0.5)
           
           if __name__ == '__main__':
               main()
           
    版本2 中存在一个全局的gen变量,需要消除
    
    - 版本3
    
                       # 协程
           import time
           import threading
           
           gen = None
           
           
           def longIo():
               print("开始耗时操作")
               time.sleep(5)
               print("结束耗时操作")
               # 返回数据
               yield "luciano is goode man "
           
           
           def genCoroutine(func):
               def wrapper(*args,**kwargs):
                   gen1 = func() # reqA的生成器
                   gen2 = next(gen1) #longIo的生成器
                   def run(g):
                       res = next(g)
                       try:
                           gen1.send(res) #返回给reqAshuju
                       except StopIteration as e:
                           pass
                   threading.Thread(target=run,args=(gen2,)).start()
               return wrapper
           
           
           @genCoroutine
           # 两个客户端的请求s
           def reqA():
               print("开始处理reqA")
               res = yield longIo()
               print("接收到longIO的数据:", res)
           
               print("结束处理reqA")
           def reqB():
               print("开始处理reqB")
               time.sleep(2)
               print("结束处理reqB")
           
           # tornado服务
           def main():
               reqA()
               reqB()
               while True:
                   time.sleep(0.5)
           
           if __name__ == '__main__':
               main()
               
    

Tornado中的异步

  • 概述:因为epoll主要是用来解决网络IO的并发问题,所以Tornado的异步也主要
    体现在网络再网络的IO上,即异步web请求

  • tornado.httpclient.AsyncHTTPClient:tornado提供的异步web请求客户端,用来进行异步
    web请求

  • fetch(request,callback=None):用于执行一个web请求,并异步相应返回一个tornado.httpclient.HTTPResponse

      参数:
          request可以是一个url,也可以是一个Tornado.httpclient.HTTPRequest对象
    
  • HTTPRequest:HTTP请求类,该类的构造函数可以接受参数 ,如果传入的是URL会自动生成一个request对象

      参数:
          url:这是字符串类型,要访问的网址(必传)
          method:字符串类型,HTTP请求方式
          headers:字典类型或o者是HTTPHeaders类型,附加的协议头
          body:,HTTP请求体
    
  • HTTPResponse :http相应类

      参数:
          code:状态码
          reason:状态码的描述
          body:响应的数据
          error:异常
    
  • 实例:

    • 回调函数

        貌似不用了
      
    • 协程

          class student02Handler(RequestHandler):
              @tornado.gen.coroutine
              def get(self,*args,**kwargs):
                  url = "https://baijiahao.baidu.com/s?id=1671161218421306732&wfr=spider&for=pc"
                  # 创房客户端
                  client = AsyncHTTPClient()
                  res = yield client.fetch(url)
                  if res.error:
                      self.send_error(500)
                  else:
                      data = json.loads(res.body)
                      self.write(data)
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值