python 异步编程 第四章 Tornado
python 异步编程 第四章 Tornado
1.1 tcp 服务器
import asyncio, timefrom tornado.iostream import StreamClosedErrorfrom tornado.tcpserver import TCPServerfrom tornado.ioloop import IOLoopclass EchoServer(TCPServer): async def handle_stream(self, stream, address): for i in range(6): try: await stream.write(f"[{time.strftime('%X')}] Count {i}\n".encode("utf-8")) await asyncio.sleep(1) except StreamClosedError: breakserver = EchoServer()server.listen(8888)try: IOLoop.current().start()except KeyboardInterrupt as e: print("Exit")
1.2 http 服务器
import tornado.ioloopimport tornado.webclass HomePage(tornado.web.RequestHandler): def get(self): self.write("hello world") # def post(sefl): # self.write("handle post request")if __name__ == '__main__': app = tornado.web.Application([ ('/', HomePage) ])
1.3 路由
import tornado.ioloopimport tornado.webimport tornado.routingclass HomePage(tornado.web.RequestHandle): def get(self): self.write("Home")class Users(tornado.web.RequestHandle): def get(self): self.wirte("Users")class AppPage(tornado.web.RequestHandler): def get(self): self.write(f"Requst path is: {self.request.path}")if __name__ == '__main__': app = tornado.web.Application([ ("/", HomePage), ("/user", Users), # 使用正则 (r"/app.*", AppPage) ]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
路径参数
import tornado.ioloopimport tornado.webimport tornado.routingclass AppPage(tornado.web.RequestHandler): def get(self, path_arg1, path_arg2): self.write(f"Arg1 is: {path_arg1}, arg2 is: {path_arg2}")if __name__ == '__main__': app = tornado.web.Application([ (r"/app/(.*)/(.*)", AppPage) ]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
多个应用
import tornado.ioloopfrom tornado.web import Applicationfrom tornado.routing import Rule, RuleRouter, PathMatchesclass HandleInApp1(tornado.web.RequestHandler): def get(self): self.write("Handle in app1")app1 = Application([ (r"/app1/handler", HandlerInApp1)])class HandleInApp2(tornado.web.RequestHandler): def get(self): self.write("Handle in app2")app2 = Application([ (r"/app2/handler", HandlerInApp2)])if __name__ == '__main__': server = tornado.web.HTTPServer( RuleRouter([ Rule(PathMatches(r"/app1.*"), app1), Rule(PathMatches(r"/app2.*"), app2) ]) ) server.listen(8888) try: tornado.ioloop.IOLoop.current().start() except KeyboardInterrupt: print("Server stopped by user")
1.4 处理静态文件
from tornado.web import Application, StaticFileHandlerfrom tornado.ioloop import IOLoopimport osAPP_ROOT = os.path.dirname(__file__)if __name__ == '__main__': app = Application([ r"/static/(.*)", StaticFileHandler, dict(path=os.path.join(APP_ROOT, "static")) ]) app.listen(8888) IOLoop.current().start()
index.html
静态文件
1.5 模版渲染
import tornado.ioloopimport tornado.webclass IndexHandler(tornado.web.RequestHandler): async def get(self): await self.render("index.html")if __name__ == '__main__': application = tornado.web.Application([ (r"/", IndexHandler) ]) tornado.ioloop.IOLoop.current().start()
index.html
静态页面
加载模板目录
import tornado.ioloopimport tornado.webimport osSERVER_ROOT = os.path.dirname(__file__)class IndexHandler(tornado.web.RequestHandler): async def get(self): await self.render("index.html")if __name__ == '__main__': application = tornado.web.Application([ (r"/", IndexHandler), ], template_path = os.path.join(SERVER_ROOT, "template")) application.listen(8888) tornado.ioloop.IOLoop.current().start()
layout.html
<!DOCTYPE html><html><head><title> Title </title></head><body> <!-- 与 jinja2 不一样,以 end 结尾 --> {% block body %}{% end %}</body></html>
index.html
{% extends "layout.html" %}{% block body %} hello world {% end %}
模板参数
import tornado.ioloopimport tornado.webimport osSERVER_ROOT = os.path.dirname(__file__)class IndexHandler(tornado.web.RequestHandler): async def get(self): await self.render("server2_index.html", user=['张三', '李四'])if __name__ == '__main__': application = tornado.web.Application([ (r"/", IndexHandler), ],template_path=os.path.join(SERVER_ROOT, "template")) application.listen(8888) tornado.ioloop.IOLoop.current().start()
server2_index.html
{% extends "layout.html" %}{% block body %}<div> Users: <ul> {% for u in users %} <li>{{ u }}</li> {% end %} </url></div>{% end %}
1.6 HTTP 客户端
server.py
import tornado.ioloopimport tornado.webclass MainHandler(tornado.web.RequestHandler): def get(self): name = self.get_query_argument("name","") self.write(f"hello {name}") def post(self): name = self.get_body_argument("name", "") self.write(f"hello {name}")if __name__ == '__main__': application = tornado.web.Application([ (r"/", MainHandler), ]) application.listen(8888) tornado.ioloop.IOLoop.current().start()
client get 请求
import tornado.httpclientimport asyncioclient = tornado.httpclient.AsyncHTTPClient()async def main(): resp = await client.fetch("http://127.0.0.1:8888?name=xiaoming") print(resp.body.decode("utf-8"))asyncio.run(main())
client post 请求
import tornado.httpclientimport asyncioclient = tornado.httpclient.AsyncHTTPClient()async def main(): resp = await client.fetch( tornado.httpclient.HTTPRequest( "http://127.0.0.1:8888", "POST", body="name=xiaoming" ) ) print(resp.body.decode("utf-8"))asyncio.run(main())