翻译:introduce to tornado - a simple example

简单的web services: html

如今咱们将开始了解什么是tornado,tornado能够作什么。咱们来经过分析tornado实现的一个简单web service 例子开始吧。python

Hello Tornado 程序员

tornado 是一个能够处理http请求的框架,你的工做是做为一个程序员,编写一个handlers来响应一个标准的http请求。,下面是这个例子的全部代码:web

范例1:hello.py正则表达式

Code      View   Copy   Print  数据库

  1. import tornado.httpserver   浏览器

  2. import tornado.ioloop   app

  3. import tornado.options   框架

  4. import tornado.web   curl

  5. from tornado.options import define, options   

  6. define(“port”, default=8000, help=”run on the given port”, type=int)   

  7.   

  8. class IndexHandler(tornado.web.RequestHandler):   

  9.     def get(self):   

  10.         greeting = self.get_argument(‘greeting’, ’Hello’)   

  11.         self.write(greeting + ’, friendly user!’)   

  12.   

  13. if __name__ == ”__main__“:   

  14.     tornado.options.parse_command_line()   

  15.     app = tornado.web.Application(handlers=[(r"/", IndexHandler)])   

  16.     http_server = tornado.httpserver.HTTPServer(app)   

  17.     http_server.listen(options.port)   

  18.     tornado.ioloop.IOLoop.instance().start()  

实际上咱们大部分的工做是使用tornado的接口去定义一个类来扩展tornado 的RequestHandler类,在这个例子中,咱们将会定义一个简单的应用来监遵从端口得到的请求,而且返回一个响应值。

你能够经过命令行去试着运行和测试你本身的代码:

  1. $ python hello.py –port=8000  

如今你能够经过浏览器访问http://localhost:8000/,或者在另一个独立的命令行窗口使用curl命令测试这个应用:

  1. $ curl http://localhost:8000/   

  2. Hello, friendly user!   

  3. $ curl http://localhost:8000/?greeting=Salutations   

  4. Salutations, friendly user!  

让咱们回到这个例子下,一步一步对它进行分析吧!

Code      View   Copy   Print  

  1. import tornado.httpserver   

  2. import tornado.ioloop   

  3. import tornado.options   

  4. import tornado.web  

在程序的最上面,咱们导入各类tornado的函数库,这里还包括更多的tornado函数库,可是在这个例子中你只须要导入四个函数库就能够运行了:

Code      View   Copy   Print  

  1. from tornado.options import define, options   

  2. define(“port”, default=8000, help=”run on the given port”, type=int)  

tornado集成了一些有用的函数在tornado.options里面,在这里咱们使用这个函数库来完成监听HTTP请求的应用,这些参数将会对全部 对象生效,若是你是在命令行中输入–help,你将会看到全部的帮助信息及其定义。若是你没有输入一个值,那么default变量后面的参数将会做为默认 值开始执行,假如你输入的是一个错误的类型,程序将会抛出一个错误,在这里容许使用一个整数型数据做为监听的端口,若是没有输入任何数据,程序将会使用默 认端口8000。

Code      View   Copy   Print  

  1. class IndexHandler(tornado.web.RequestHandler):   

  2.     def get(self):   

  3.         greeting = self.get_argument(‘greeting’, ’Hello’)   

  4.         self.write(greeting + ’, friendly user!’)  

这是一个tornado处理请求的类,当出现请求时,tornado实例将会调用这个类和方法。在这个例子中,咱们只定义了一个get方法,这意味着程序只能处理HTTP GET的请求,在后面咱们将会学习到如何使用更多接口去响应HTTP不一样的请求。

 

Code      View   Copy   Print  

  1. greeting = self.get_argument(‘greeting’, ’Hello’)  

tornado的请求类拥有不少有用的方法,好比get_argument,这个方法可让咱们得到请求字符串中的变量(若是请求中不包含字符串,tornado将会使用第二种方法替代get_argument,并使用默认值)

Code   ViewCopyPrint

  1. self.write(greeting + ‘, friendly user!’)

第二个方法是使用一个请求的方法,当请求中有字符串变量时,咱们将会获取这个字符串,而且插入一个问候语响应这条请求。

 

Code      View   Copy   Print  

  1. if __name__ == ”__main__“:   

  2.     tornado.options.parse_command_line()   

  3.     app = tornado.web.Application(handlers=[(r"/", IndexHandler)])  

tornado的应用将会从这里开始执行,首先咱们经过tornado的options函数库去解析命令,当咱们建立一个tornado应用类的实例的时 候,全部导入的变量将会传送到类的__init__方法中,这个方法将会告诉tornado须要调用哪个handle ,咱们将会在后面对此作详细的说明。

 

  1. http_server = tornado.httpserver.HTTPServer(app)   

  2. http_server.listen(options.port)   

  3. tornado.ioloop.IOLoop.instance().start()  

程序将从这里开始执行,建立一个实例,咱们经过应用tornado的HTTPServer对象来监听指定的端口在命令行中获取的数据,而后咱们建立一个tornado的IOLoop实例,最后这个程序将会开始接收HTTP请求。

操做的变量

让咱们再回头看看helly.py这个例子的第一行:

app = tornado.web.Application(handlers=[(r"/", IndexHandler)])

这个handlers很是重要,咱们将会在后面对它进行更详细的解释,它是一个元组的列表,咱们使用一个正则表达式将它与RequestHandler进行匹配,你能够添加更多的列表来指定更多须要匹配的RequestHandler。

 

使用正则表达式来指定URL

tornado使用正则表达式来匹配URL的http请求(RequestHandler的类在URL后面,不包括主机名和查询字符串的片断),它们应该 包含起始行和结束行。当一个正则表达式匹配一个HTTP请求时,匹配的内容将会做为参数传递给RequestHandler的类。咱们将会在下一个例子了 解到它是如何工做的。

 

字符串服务

咱们将经过一个稍微复杂一些的例子1-2去介绍更多关于tornado的设计理念.

例1-2 Handling input: string_service.py

Code      View   Copy   Print  

  1. import textwrap  

  2. import tornado.httpserver   

  3. import tornado.ioloop   

  4. import tornado.options   

  5. import tornado.web   

  6. from tornado.options import define, options   

  7. define(“port”, default=8000, help=”run on the given port”, type=int)   

  8. class ReverseHandler(tornado.web.RequestHandler):   

  9.     def get(selfinput):   

  10.         self.write(input[::-1])   

  11.   

  12. class WrapHandler(tornado.web.RequestHandler):   

  13.     def post(self):   

  14.         text = self.get_argument(‘text’)   

  15.         width = self.get_argument(‘width’, 40)   

  16.         self.write(textwrap.fill(text, width))   

  17.   

  18. if __name__ == ”__main__“:   

  19.     tornado.options.parse_command_line()   

  20.     app = tornado.web.Application(   

  21.         handlers=[   

  22.             (r"/reverse/(\w+)", ReverseHandler),   

  23.             (r"/wrap", WrapHandler)   

  24.         ]   

  25.     )   

  26.     http_server = tornado.httpserver.HTTPServer(app)   

  27.     http_server.listen(options.port)   

  28.     tornado.ioloop.IOLoop.instance().start()  

和第一个例子同样,你能够像这样在命令行中运行它

  1. $ python string_service.py –port=8000  

这个程序是一个用于处理字符串的基础web框架,如今你能够对它作两件事情。

第一:经过GET向 /reverse/string请求返回一个特定的字符串,相似这样的URL结构

Code      View   Copy   Print  

  1. $ curl http://localhost:8000/reverse/stressed   

  2. desserts   

  3. $ curl http://localhost:8000/reverse/slipup   

  4. pupils  

第二:经过POST向/wrap提交请求,并将返回的字符串显示出来。这个请求包括一个无长度限制的字符串,在程序中,咱们经过get_argument来接收这个字符串变量。你能够这么测试:

  1. $ curl http://localhost:8000/wrap »   

  2. -d text=Lorem+ipsum+dolor+sit+amet,+consectetuer+adipiscing+elit.   

  3. Lorem ipsum dolor sit amet, consectetuer   

  4. adipiscing elit.  

 curl命令显示的是两行命令,可是咱们输入的应该只是一行的命令,因此咱们使用双引字符(>>)来表示命令行的延续

这个字符串服务的例子大部分代码和上一个例子是相同的,让咱们将注意力集中到那些新增的不一样代码中来,首先让咱们来看看程序中传送给handlers的变量有什么不一样:

Code      View   Copy   Print  

  1. app = tornado.web.Application(handlers=[   

  2.     (r"/reverse/(\w+)", ReverseHandler),   

  3.     (r"/wrap", WrapHandler)   

  4. ])  

在这个例子的代码中,咱们能够看到有两个RequestHandlers实例化的类对Handlers进行处理,第一个tornado请求的地址按照下面的正则表达式进行匹配:

Code      View   Copy   Print  

  1. /reverse/(\w+)  

这个正则表达式告诉tornado,他将会匹配一个/reverse/后面跟着一个或多个数字、字母的字符串,括号的含义是告诉tornado,须要将括 号中匹配的字符串做为RequestHandler的请求参数,咱们能够查看ReverseHandler的定义去了解它是如何工做的:

Code      View   Copy   Print  

  1. class ReverseHandler(tornado.web.RequestHandler):   

  2.     def get(selfinput):   

  3.         self.write(input[::-1])  

你能够看到这个类中,get方法须要输入一个额外的参数,这个参数是在第一个正则表达式中,彻底匹配括号内的表达式的一个字符串,(假若有多个括号分割的正则表达式,能够按照相同的顺序在get中添加接收的参数的变量)

如今,让咱们来看看WrapHandler的定义:

Code      View   Copy   Print  

  1. class WrapHandler(tornado.web.RequestHandler):   

  2.     def post(self):   

  3.         text = self.get_argument(‘text’)   

  4.         width = self.get_argument(‘width’, 40)   

  5.         self.write(textwrap.fill(text, width))  

WrapHandler的类会处理从请求中传过来的字符串。咱们能够看到这个类只定义了一个post的方法,这意味着它只能接收HTTP post的方法。咱们以前是用过这个RequestHandler对象来抓取从请求中传过来的字符串做为变量。如今咱们可使用一样的方法去抓取POST 请求传过来的变量(tornado能够解析POST传过来的URL字符串或参数),一旦咱们抓取到了字符串及其长度的参数,就可使用python内置的 textwrap函数库库去转换字符串,而且经过HTTP返回生成的字符串做为响应数据。

 

更多RequestHandlers

到目前为止,咱们基于RequestHandler开发这些对象:如何经过HTTP获取参数(使用get_argument 获取GET和POST传递过来的参数)和如何编写HTTP相应信息(使用write方法)。在咱们开始后面的章节学习以前,再给你介绍一些应用 RequestHandler须要注意的地方,以及tornado如何去使用它。

http方法:

截止目前讨论的都是关于RequestHandler定义单个HTTP方法的问题,其实在一个类中,能够定义或使用多个 handler,绑定多个功能到一个类中是一种很好的管理方式,你可能会编写一个处理程序去获取参数,而且经过POST和GET对象改变数据库中一个特定 ID的值,例如:用一个GET方法中将抓取请求的ID和参数,而且使用POST方法修改数据库中对应ID的值。

Code      View   Copy   Print  

  1. # matched with (r”/widget/(\d+)”, WidgetHandler)   

  2. class WidgetHandler(tornado.web.RequestHandler):   

  3.     def get(self, widget_id):   

  4.         widget = retrieve_from_db(widget_id)   

  5.         self.write(widget.serialize())   

  6.     def post(self, widget_id):   

  7.         widget = retrieve_from_db(widget_id)   

  8.         widget['foo'] = self.get_argument(‘foo’)   

  9.         save_to_db(widget)  

截止目前咱们讨论的例子中只使用了GET 和 POST的方法,实际上tornado还支持更多的HTTP方法(GET,POST,PUT,DELETE,HEAD,OPTIONS),在你编写的 RequestHandler类中能够经过定义不一样的方法去使用他们。在下面的虚拟案例中,咱们将会使用HEAD方法去判断请求中的frob是否存在于数 据库中,当存在时咱们经过GET方法将frob对应的数据库信息返回给请求的客户端:

Code      View   Copy   Print  

  1. # matched with (r”/frob/(\d+)”, FrobHandler)   

  2. class FrobHandler(tornado.web.RequestHandler):   

  3.     def head(self, frob_id):   

  4.         frob = retrieve_from_db(frob_id)   

  5.         if frob is not None:   

  6.             self.set_status(200)   

  7.         else:   

  8.             self.set_status(404)   

  9.     def get(self, frob_id):   

  10.         frob = retrieve_from_db(frob_id)   

  11.         self.write(frob.serialize())  

HTTP状态码:

在上一个展现的例子中,你能够在你的RequestHandler使用set_status()设置HTTP状态码到客户端的相应信息中,下面是一些比较重要的状态码。tornado也能够根据你的相应自动去返回对应的状态码,在这里咱们只列出比较经常使用的几个状态码:

404 Not Found

若是HTTP请求的路径不存在,tornado将会经过RequestHandler类自动将404(Not Found)返回给客户端

400 Bad Request

若是使用get_argument没有获取到默认的参数哦,或者没有找到定义的参数名,tornado将会自动将400(Bad Request)返回给客户端。

405 Method Not Allowed

若是经过HTTP传进来的请求没有找到RequestHandler类中对应的方法(例如使用POST请求,可是handler方法对应的类倒是GET方法)tornado将会返回一个405(Method Not Allowed)给客户端。

500 Internal Server Error

当遇到任何应用服务异常退出的错误时,tornado将会返回500( Internal Server Error)给客户端,代码中任何意外退出均可能致使tornado返回一个500错误代码。

200 OK

若是请求成功完成了,而且没有设置其它相应代码,tornado默认将会自动返回一个200(OK)的响应给客户端。

当出现一个错误出现时,tornado默认将会发送一个包含错误代码和错误信息的html页面给客户端,若是你想要替换默认响应的错误信息成自定义的页 面,你能够在你的RequestHandler中重写write_error方法,例子1-3将会向你展现咱们修改的hello.py,让你了解如何将初 始化的错误信息从新改写。

Code      View   Copy   Print  

  1. import tornado.httpserver   

  2. import tornado.ioloop   

  3. import tornado.options   

  4. import tornado.web   

  5. from tornado.options import define, options   

  6. define(“port”, default=8000, help=”run on the given port”, type=int)   

  7. class IndexHandler(tornado.web.RequestHandler):   

  8.     def get(self):   

  9.         greeting = self.get_argument(‘greeting’, ’Hello’)   

  10.         self.write(greeting + ’, friendly user!’)   

  11.     def write_error(self, status_code, **kwargs):   

  12.         self.write(“Gosh darnit, user! You caused a %d error.” % status_code)   

  13. if __name__ == ”__main__“:   

  14.     tornado.options.parse_command_line()   

  15.     app = tornado.web.Application(handlers=[(r"/", IndexHandler)])   

  16.     http_server = tornado.httpserver.HTTPServer(app)   

  17.     http_server.listen(options.port)   

  18.     tornado.ioloop.IOLoop.instance().start()  

在当咱们使用POST向handler发送请求时,将会出现下面的响应,由于咱们已经把tornado默认的错误响应重写了:

Code      View   Copy   Print  

  1. $ curl -d foo=bar http://localhost:8000/   

  2. Gosh darnit, user! You caused a 405 error.  

下一步

如今你对tornado已经有了基本的理解,咱们但愿你能有迫切学习更多知识的动力。在后续的章节,咱们将向你展现更多的功能和技术,帮助你使用tornado去创建一个完整的web server和web应用。

原创翻译,首发地址:http://blog.xihuan.de/tech/web/tornado/

上一篇:翻译:introduce to tornado - introduce

下一篇:翻译:introduce to tornado - form and template

相关文章
相关标签/搜索