I’ve been playing around with Tornado a bit and wanted to asynchronously call a long-running shell command without blocking the server process. Here is my solution.
Running this server I am able to visit http://localhost:8888/test/ numerous times while a request for http://localhost:8888/ is waiting for the command to finish. The beauty of this is that this is a single process with a single thread. With a process this light and fast, a relatively large number of applications can be crammed into a $10/mo hosted account.
#!/usr/bin/env python
import os
import tornado.httpserver
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
self.ioloop = tornado.ioloop.IOLoop.instance()
self.pipe = p = os.popen('sleep 5; cat /etc/mime.types')
self.ioloop.add_handler( p.fileno(), self.async_callback(self.on_response), self.ioloop.READ )
def on_response(self,fd,events):
for line in self.pipe:
self.write( line )
self.ioloop.remove_handler(fd)
self.finish()
class TestHandler(tornado.web.RequestHandler):
def get(self):
self.write('this is a test')
application = tornado.web.Application([
(r"/", MainHandler),
(r"/test/", TestHandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
