Starting with Tornado in Python: Setting Up Your Server

E

ehansen

Guest
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
 


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.
 


Top