1.编译安装tornado:
$ curl -L -O https://github.com/facebook/tornado/archive/v3.1.0.tar.gz $ tar xvzf v3.1.0.tar.gz $ cd tornado-3.1.0 $ python setup.py build $ sudo python setup.py install
Tornado官方并不支持Windows,但你可以通过ActivePython的PyPM包管理器进行安装,类似如下所示:
C:\> pypm install tornado
2.一个简单的tornado服务器:server.py
import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int) class IndexHandler(tornado.web.RequestHandler): def get(self): greeting = self.get_argument('greeting', 'Hello') self.write(greeting + ', friendly user!') if __name__ == "__main__": tornado.options.parse_command_line() app = tornado.web.Application(handlers=[(r"/", IndexHandler)]) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
运行服务器:
$ python server.py --port=8000
测试:在浏览器中打开http://localhost:8000,或者 使用curl测试
$ curl http://localhost:8000/ Hello, friendly user! $ curl http://localhost:8000/?greeting=Salutations Salutations, friendly user!
3.分析:
一个最基本的tornado服务器,必须至少包含这四个模块:tornado.options、tornado.web、tornado.httpserver、tornado.ioloop
1)tornado.options:用来从命令行读取设置。当然,也可以将设置写死,不从命令行读取。
定义示例:
from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int)
使用示例:
$ python server.py --port=9000
from tornado.options import define, options print (options.port) # options.port将作为全局设置,返回值9000
工作流程:
如果一个与define语句中同名的设置在命令行中被给出,那么它将成为全局options的一个属性。
- 第一个参数:参数名称
- default参数:如果没有在命令行中给出此名称的参数,则使用default的值进行代替。
- type参数:进行基本的参数类型验证
在命令行中,使用--help
选项,将打印出所有你定义的选项以及你在define函数的help参数中指定的文本。
2)tornado.web.RequestHandler:请求处理函数的类
示例:
class IndexHandler(tornado.web.RequestHandler): def get(self): greeting = self.get_argument('greeting', 'Hello') self.write(greeting + ', friendly user!')
当处理一个请求时:Tornado将这个类IndexHandler实例化,并调用与HTTP请求方法(如此处的HTTP请求方法,假设为:GET),所对应的方法(如这里定义的self.get()方法)。
也就是说,当一个get请求到来时,将实例化IndexHandler,并且调用此实例的self.get()方法,如果有。
当一个post请求到来时,将将实例化IndexHandler,并且调用此实例的self.post()方法,如果有。---这里没有定义post方法,因此对于POST请求,是不会处理的。
同时,RequestHandler类的实例,有一系列的方法,
RequestHandler类的参数处理方法:
- self.get_argument('apiName', 'default_value') 获取名称为"apiName"的参数(包括query和post在内的所有参数)
- self.request.query_arguments 获取所有的查询参数
- self.request.body.decode('utf-8') 获取所有的post参数
- self.request.body_arguments 获取所有的post参数
RequestHandler类的响应方法:
- self.write(string) 将一个字符串写入到HTTP响应中
- self.finish(string) 将一个字符串写入到HTTP响应中
- self.render(a_html_file) 将一个html模板渲染到HTTP响应中
RequestHandler类显示设置状态码:self.set_status()
Tornado会自动地设置HTTP状态码,如400,404,405,500,200........
当上述任何一种错误发生时,Tornado将默认向客户端发送一个包含状态码和错误信息的简短片段。
如果你想使用自己的方法代替默认的错误响应,你可以在你的RequestHandler类中,重写write_error方法。
RequestHandler类的错误处理方法:self.write_error()
示例:
class IndexHandler(tornado.web.RequestHandler): def get(self): greeting = self.get_argument('greeting', 'Hello') self.write(greeting + ', friendly user!') def write_error(self, status_code, **kwargs): self.write("Gosh darnit, user! You caused a %d error." % status_code)
当我们尝试一个POST请求时,如果没有覆写write_error方法,会得到Tornado默认的错误响应。
tornado.web.HTTPError: HTTP 405: Method Not Allowed
但因为我们覆写了write_error,我们会得到不一样的错误响应:
$ curl -d foo=bar http://localhost:8000/
Gosh darnit, user! You caused a 405 error.
3)tornado.web.Application:路由app
示例
if __name__ == "__main__": tornado.options.parse_command_line() app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
tornado.options.parse_command_line():用来解析命令行中的参数
Application(handlers=[(r"/", IndexHandler)]),创建路由app实例:它告诉Tornado,用哪个类来响应哪个url的请求
这里非常重要,handlers指明了路由,是一个列表,列表内是多个元组;元组的第一个参数是一个用于匹配的正则表达式,指明url路径;第二个参数handlers,相当于django的视力函数。
Tornado在元组中使用正则表达式来匹配HTTP请求的路径。(这个路径是URL中主机名后面的部分,不包括查询字符串和碎片。)Tornado把这些正则表达式看作已经包含了行开始和结束锚点(即,字符串"/"被看作为"^/$")。
Application,除了指明路由,还可以指明其它参数,如:
bases = dict( # blog_title=u"F2E Community", template_path=os.path.join(os.path.dirname(__file__), os.pardir, "templates"), static_path=os.path.join(os.path.dirname(__file__), "static"), xsrf_cookies=xsrf_cookies, # True或False debug=base.ENV == "DEBUG" and True or False, cookie_secret="cookie_secret_code", # login_url="/login", autoescape=None, # reserved=["user", "topic", "home", "base", "forgot", "login", "logout", "register", "admin"], handlers=route_list, autoreload=True ) Application(**bases)
4)运行服务器:
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
从这里开始的代码将会被反复使用:一旦Application对象被创建,将其传递给Tornado的HTTPServer对象,然后使用在命令行指定的端口进行监听(通过options对象取出)。最后,在程序准备好接收HTTP请求后,我们创建一个Tornado的IOLoop的实例。