同步与异步复习
python实现异步的两种方法
使用回调函数实现异步 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import time import threading
def task1(callback): def run(callback): print('开始耗时操作') time.sleep(2) print('结束耗时操作') callback('hello world') threading.Thread(target=run,args=(callback,)).start()
def finish(data): print('开始处理回调函数') print('接收到task1的响应数据',data) print('结束处理回调函数')
if __name__ == '__main__': task1(finish)
|
使用协程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import time import threading
global gen
def reqA(): print('reqA start') res = yield longIO() print('接受到longIO的响应数据:',res) print('reqA end')
def reqB(): print('reqB start') time.sleep(2) print('reqB end')
def longIO(): def run(): print('start longIO') time.sleep(2) try: print('++++++++') global gen gen.send('hello') except StopIteration as e: pass threading.Thread(target=run).start()
def main(): global gen gen = reqA() next(gen)
print('****************') reqB()
main()
|
Tornado中的异步
因为epoll主要是用来解决网络的并发间题,所以 Tornado的异步也是主要体现在网络的异步上,即异步Web请求
1 2
| (r'/test10',views.index.TestHandler10), (r'/test11',views.index.TestHandler11),
|
1 2 3 4 5 6 7 8
| class TestHandler10(tornado.web.RequestHandler): def get(self,*args,**kwargs): time.sleep(20) self.write('test10')
class TestHandler11(tornado.web.RequestHandler): def get(self,*args,**kwargs): self.write('test11')
|
此时先后访问http://127.0.0.1:8000/test10
和http://127.0.0.1:8000/test11
, 那么,test'11
会阻塞20秒,等待test10
响应完了才返回结果
tornado.httpclient.AsyncHTTPClient
: tornado提供的异步Web请求客户端,用来进行异步Web请求
fetch(request,callback=None)
: 用于执行一个Web请求 , 并异步响应返回一个tornado.httpclient.HTTPResponse
- request可以是一个url , 也可以是一个Tornado.httpclient.HTTPRequest对象
- 如果是一个url , 后台会自动转为request对象
tornado.web.asynchronous
: 不关闭通信的通道
HTTPRequest :
参数 :
- url : 字符串类型,必传
- method : 字符串类型
- headers : 字典或者HTTPHeaders
- body : HTTP请求体
HTTPResponse :
参数 :
- code : 状态码
- readson : 状态码的描述
- body : 响应的数据
- error : 异常
回调函数实现异步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import json from tornado.httpclient import AsyncHTTPClient
class TestHandler10(tornado.web.RequestHandler): def on_response(self,response): if response.error: self.send_error(500) else: data = json.loads(response.body) self.write(data) self.finish()
@tornado.web.asynchronous def get(self,*args,**kwargs): url = 'https://www.baidu.com/' client = AsyncHTTPClient() client.fetch(url,self.on_response) self.write('test10')
|
协程实现异步
1 2 3 4 5 6 7 8 9 10 11 12
| class TestHandler11(tornado.web.RequestHandler): @tornado.gen.coroutine def get(self,*args,**kwargs): url = 'https://www.baidu.com/' client = AsyncHTTPClient() res = yield client.fetch(url)
if res.error: self.send_error(500) else: data = json.loads(res.body) self.write(data)
|
上面的逻辑比较乱 , 这时就可以分离一下请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class TestHandler11(tornado.web.RequestHandler): @tornado.gen.coroutine def get(self,*args,**kwargs): res = yield self.get_data() self.write(res)
@tornado.gen.coroutine def get_data(self,*args,**kwargs): url = 'https://www.baidu.com/' client = AsyncHTTPClient() res = yield client.fetch(url)
if res.error: ret = {'ret':0} else: ret = json.loads(res.body) raise tornado.gen.Return(ret)
|