Starting with Tornado in Python: Setting Up Your Server

Discussion in 'Linux Server' started by ehansen, Jul 9, 2013.

  1. ehansen

    ehansen New Member Staff Writer

    Messages:
    115
    Likes Received:
    11
    Trophy Points:
    0
    There's a good collection of different Python modules to use so you can run a server through Python (think SimpleHTTPServer). One that is commonly used behind Nginx proxies for handling API requests, however, is Tornado (http://www.tornadoweb.org/). Since creating my backup service I have chosen Tornado as the backend to my API to provide an efficient and secure service to allow users to write their own clients.

    Installing Tornado
    To install Tornado all you have to do is this in Pypi:
    Code:
    pip install tornado
    
    If you don't have Pypi installed, then you can install it from sources:


    Code:
    python set.py install
    
    This will install Tornado in your Python repos so you can now simply import it into your scripts. Now to cover some simple usages.

    Initializing Tornado
    The main thing we are going to focus on right now is setting up a simple 'web' server. This will allow you to have Tornado listen for connections and handle them appropriately. To start, import Tornado's HTTP web server code:

    Code:
    import tornado.httpserver
    
    We also need a reference to I/O handlers, so we need ioloop:

    Code:
    import tornado.ioloop
    
    To make this easy on us we will define a main() function:

    Code:
    def main(port = 8888):
    
    The magic inside is what makes this work.

    Lets say we wanted to serve content from our server with a specific URI only. We'll make this URI /get/sysinfo and /get/cpuinfo. Our main() method will look like this:

    Code:
    def main(port = 8888):                                                                                                 
    ioloop = tornado.ioloop.IOLoop.instance()
    application = tornado.web.Application([
    (r"/get/(sysinfo|cpuinfo)", InfoHandler)
    ])
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(port)
    try:
    ioloop.start()
    except KeyboardInterrupt:
    pass
    
    tornado.ioloop.IOLoop.instance() creates an instance of our I/O so we can send/receive network data. application is our reference to our tornado.httpserver instance, and we tell it to listen for /get/sysinfo and /get/cpuinfo requests, and forward them to our InfoHandler class which I will show in a bit. We then have our web server listening on the specified port, and try to start it. The exception is in place in case you are running this manually, so if you do Ctrl+C no Traceback information is displayed.

    Now that we have Tornado checking for a request, we need to be able to handle such requests. This is where our infoHandler class comes in.

    Handling Requests
    Code:
    class InfoHandler(tornado.web.RequestHandler):                                                                                                                                                                                         
    
    Code:
     def get(self, call):
    try:
    resp = valid_calls[call]
    self.write(resp)
    self.finish()
    except:
    # log error message
    pass
    We need to subclass the RequestHandler class so we can read and write data on the stream. To write data back to the user use self.write(<data>), and to get data from the user you simply call self.get_argument(<name>). So if someone sent the URI: /get/cpuinfo?core=1 you would do core = self.get_argument('core').

    What is valid_calls[]? This is a dictionary of 'key' : 'value" where the key is the request being made (i.e.: 'sysinfo' and 'cpuinfo') and the value being a reference to the function. For example:
    Code:
    def SysInfo():
    return "sysinfo printed from here"
     
    valid_calls = {'sysinfo' : SysInfo}
    To get this up and running we then just do a simple name check and call main:
    Code:
    if __name__ == "__main__":
    try:
    import sys
    main(sys.argv[1])
    except:
    main()
    else:
    pass
  2. kshitij.mittal01

    kshitij.mittal01 New Member

    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    1
    In order to install Pypi, rather than using "python set.py install", we have to use "python setup.py install". Looks like a typo here.

Share This Page