tonardo学习之路
异步原理
blockio.py
#阻塞io import requests # html = requests.get("http://www.baidu.com").text # #1. 三次握手建立tcp连接, # # 2. 等待服务器响应 # print(html) #如何通过socket直接获取html import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = "www.baidu.com" client.connect((host, 80)) #阻塞io, 意味着这个时候cpu是空闲的 client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format("/", host).encode("utf8")) data = b"" while 1: d = client.recv(1024) #阻塞直到有數據 if d: data += d else: break data = data.decode("utf8") print(data)
noblockio.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.setblocking(False) host = "www.baidu.com" try: client.connect((host, 80)) #阻塞io, 意味着这个时候cpu是空闲的 except BlockingIOError as e: #做一些其他事 pass while 1: try: client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format("/", host).encode("utf8")) print("send success") break except OSError as e: pass data = b"" while 1: try: d = client.recv(1024) #阻塞直到有數據 except BlockingIOError as e: continue if d: data += d else: break data = data.decode("utf8") print(data)
selector.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket from selectors import DefaultSelector, EVENT_WRITE, EVENT_READ selector = DefaultSelector()#根据操作系统自动选择select或者epoll class Fetcher: def connected(self, key): selector.unregister(key.fd) self.client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format("/", self.host).encode("utf8")) selector.register(self.client.fileno(), EVENT_READ, self.readble) def readble(self, key): d = self.client.recv(1024) if d: self.data += d else: selector.unregister(key.fd) data = self.data.decode("utf8") print(data) def get_url(self, url): self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client.setblocking(False) self.data = b"" self.host = "www.baidu.com" try: self.client.connect((self.host, 80)) # 阻塞io, 意味着这个时候cpu是空闲的 except BlockingIOError as e: # 做一些其他事 pass selector.register(self.client.fileno(), EVENT_WRITE, self.connected) def loop_forever(): #事件循环 while 1: ready = selector.select() for key, mask in ready: call_back = key.data call_back(key) if __name__ == "__main__": fetcher = Fetcher() url = "http://www.baidu.com" fetcher.get_url(url) loop_forever()
coroutine.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#1. 什么是协程 #1.回调过深造成代码很难维护 #2.栈撕裂造成异常无法向上抛出 #协程- 可以被暂停并切换到其他协程运行的函数 from tornado.gen import coroutine async def yield_test(): yield 1 yield 2 yield 3 async def main(): result = await yield_test() async def main2(): await yield_test() my_yield = yield_test() for item in my_yield: print(item)
asynhttpclient.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from tornado import httpclient # # http_client = httpclient.HTTPClient() # try: # response = http_client.fetch("http://www.tornadoweb.org/en/stable/") # print(response.body.decode("utf8")) # except httpclient.HTTPError as e: # # HTTPError is raised for non-200 responses; the response # # can be found in e.response. # print("Error: " + str(e)) # except Exception as e: # # Other errors are possible, such as IOError. # print("Error: " + str(e)) # http_client.close() #异步方式,代码写法和同步无太大差别 async def f(): http_client = httpclient.AsyncHTTPClient() try: response = await http_client.fetch("http://www.tornadoweb.org/en/stable/") except Exception as e: print("Error: %s" % e) else: print(response.body.decode("utf8")) if __name__ == "__main__": import tornado io_loop = tornado.ioloop.IOLoop.current() #run_sync方法可以在运行完某个协程之后停止事件循环 io_loop.run_sync(f)