tornado学习一:一个基本的tornado服务器


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的实例。

 

 

 


 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM