Tornado 学习笔记 Tornado基础 1
内容原子官方文档:
Tornado基础
Tornado是一套web框架和异步网络功能库,使用非阻塞式IO,可支持数万个活动连接。支持长活跃连接,支持long polling长连接,支持WebSockets。
A web framework (includingRequestHandlerwhich is subclassed to create web applications, and various supporting classes).
Client- and server-side implementions of HTTP (HTTPServerandAsyncHTTPClient).
An asynchronous networking library (IOLoopandIOStream), which serve as the building blocks for the HTTP components and can also be used to implement other protocols.
A coroutine library (tornado.gen) which allows asynchronous code to be written in a more straightforward way than chaining callbacks.
●一个web框架,包含RequestHandler 用于创建web应用程序。
●客户端和服务端HTTP实现(HTTPServerandAsyncHTTPClient)。
●异步网络库(IOLoopandIOStream),可以用来建立HTTP组件,还可以实现其他协议。
●一个协程库(tornado.gen),可允许比链式回调地更加直接地编写使用异步代码。
Tornado可以作为WSGI容器,也可以被包含在其他WSGI容器。
的几种异步接口:
Callback argument
Return a placeholder (Future,Promise,Deferred)
Deliver to a queue
Callback registry (e.g. POSIX signals)
●回调参数
●返回一个占位类(Future,Promise,Deferred)
●递交到队列
●回调注册(例如POSIX信号)
同步方式的代码示例:
fromtornado.httpclientimportHTTPClientdefsynchronous_fetch(url):http_client=HTTPClient()response=http_client.fetch(url)returnresponse.body
回调方式的示例代码:
fromtornado.httpclientimportAsyncHTTPClientdefasynchronous_fetch(url,callback):http_client=AsyncHTTPClient()defhandle_response(response):callback(response.body)http_client.fetch(url,callback=handle_response)
使用Future的示例代码:
fromtornado.concurrentimportFuturedefasync_fetch_future(url):http_client=AsyncHTTPClient()my_future=Future()fetch_future=http_client.fetch(url)fetch_future.add_done_callback(lambdaf:my_future.set_result(f.result()))returnmy_future
使用gen和协程方式的实例代码:
fromtornadoimportgen@gen.coroutinedeffetch_coroutine(url):http_client=AsyncHTTPClient()response=yieldhttp_client.fetch(url)raisegen.Return(response.body)
另一个gen和协程的实现代码:
fromtornadoimportgen@gen.coroutinedeffetch_coroutine(url):http_client=AsyncHTTPClient()response=yieldhttp_client.fetch(url)returnresponse.body
包含yield的函数是一个generator,它是异步的,返回generator对象无需等到运行完成。
defrun(self):#send(x)makesthecurrentyieldreturnx.#Itreturnswhenthenextyieldisreachedfuture=self.gen.send(self.next)defcallback(f):self.next=f.result()self.run()future.add_done_callback(callback)
协程调用模式
和回调交互:将调用包裹在Task中,可以返回一个Future对象,并加入回调的参数。
@gen.coroutinedefcall_task():#Notethattherearenoparensonsome_function.#ThiswillbetranslatedbyTaskinto#some_function(other_args,callback=callback)yieldgen.Task(some_function,other_args)
调用阻塞函数:使用ThreadPoolExecutor,可以返回和协程兼容的Future。
thread_pool=ThreadPoolExecutor(4)@gen.coroutinedefcall_blocking():yieldthread_pool.submit(blocking_func,args)
并行执行:协程装饰器能识别类型为Futures的列表和字典,并且等待所有这些Future并行执行完成
@gen.coroutinedefparallel_fetch(url1,url2):resp1,resp2=yield[http_client.fetch(url1),http_client.fetch(url2)]@gen.coroutinedefparallel_fetch_many(urls):responses=yield[http_client.fetch(url)forurlinurls]#responsesisalistofHTTPResponsesinthesameorder@gen.coroutinedefparallel_fetch_dict(urls):responses=yield{url:http_client.fetch(url)forurlinurls}#responsesisadict{url:HTTPResponse}
交替执行:有些时候需要保存Future而不是让他立即执行,可以在等待时开始一个新的操作
@gen.coroutinedefget(self):fetch_future=self.fetch_next_chunk()whileTrue:chunk=yieldfetch_futureifchunkisNone:breakself.write(chunk)fetch_future=self.fetch_next_chunk()yieldself.flush()
循环:需要从访问的结果拆解循环条件,类似在Motor中的用法
importmotordb=motor.MotorClient().test@gen.coroutinedefloop_example(collection):cursor=db.collection.find()while(yieldcursor.fetch_next):doc=cursor.next_object()
基本程序结构
fromtornado.ioloopimportIOLoopfromtornado.webimportRequestHandler,Application,urlclassHelloHandler(RequestHandler):defget(self):self.write("Hello,world")defmake_app():returnApplication([url(r"/",HelloHandler),])defmain():app=make_app()app.listen(8888)IOLoop.current().start()
Application和路由
classMainHandler(RequestHandler):defget(self):self.write('<ahref="%s">linktostory1</a>'%self.reverse_url("story","1"))classStoryHandler(RequestHandler):definitialize(self,db):self.db=dbdefget(self,story_id):self.write("thisisstory%s"%story_id)app=Application([url(r"/",MainHandler),url(r"/story/([0-9]+)",StoryHandler,dict(db=db),name="story")])
处理输入请求
可以使用get_query_argumentandget_body_argument方法,获取get或表单的数据
classMyFormHandler(RequestHandler):defget(self):self.write('<html><body><formaction="/myform"method="POST">''<inputtype="text"name="message">''<inputtype="submit"value="Submit">''</form></body></html>')defpost(self):self.set_header("Content-Type","text/plain")self.write("Youwrote"+self.get_body_argument("message"))
如果数据是json方式的
defprepare(self):ifself.request.headers["Content-Type"].startswith("application/json"):self.json_args=json.loads(self.request.body)else:self.json_args=None
write_error- 输出HTML的错误页面。
on_connection_close- 客户端断开连接时调用; 应用程序可以检测这种情况 并终止后续的处理。 注意不能保证连接断开的检测是准确的。
get_current_user- 参看User authentication (用户授权)
get_user_locale- 返回Locale对象给当前的用户
set_default_headers- 可以用于设置附加的html相应头 (例如自定义Server头)
错误处理
RequestHandler.write_error 用来产生一个错误页。
tornado.web.HTTPError用来产生错误状态码。
重定向
可以通过两种方式实现重定向。
RequestHandler.redirectand with theRedirectHandler.
RedirectHandler用于配置重定向在路由中。
app=tornado.web.Application([url(r"/app",tornado.web.RedirectHandler,dict(url="http://itunes.apple.com/my-app-id")),])
支持正则表达式
app=tornado.web.Application([url(r"/photos/(.*)",MyPhotoHandler),url(r"/pictures/(.*)",tornado.web.RedirectHandler,dict(url=r"/photos/\1")),])
异步处理
异步处理通常可以使用两种形式:
coroutine装饰器 + yield关键字
tornado.web.asynchronous装饰器 + callback ,请求会一直保持打开,callback完成返回时调用RequestHandler.finish,响应这时再发出
callback模式的示例,使用内置的AsyncHTTPClient:
classMainHandler(tornado.web.RequestHandler):@tornado.web.asynchronousdefget(self):http=tornado.httpclient.AsyncHTTPClient()http.fetch("http://friendfeed-api.com/v2/feed/bret",callback=self.on_response)defon_response(self,response):ifresponse.error:raisetornado.web.HTTPError(500)json=tornado.escape.json_decode(response.body)self.write("Fetched"+str(len(json["entries"]))+"entries""fromtheFriendFeedAPI")self.finish()
协程模式的示例:
classMainHandler(tornado.web.RequestHandler):@tornado.gen.coroutinedefget(self):http=tornado.httpclient.AsyncHTTPClient()response=yieldhttp.fetch("http://friendfeed-api.com/v2/feed/bret")json=tornado.escape.json_decode(response.body)self.write("Fetched"+str(len(json["entries"]))+"entries""fromtheFriendFeedAPI")
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。