同步与异步
同步
- 按部就班的依次执行代码
异步
-
概述:对于耗时的操作交给别人(另一个线程)去处理,我们继续向下去执行,
当别人结束耗时操作后再将结果反馈给我们 -
回调函数实现异步
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)
-