EzDev.org

tornado

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. Tornado Web Server — Tornado 4.2.1 documentation


Non-blocking ORM for Tornado?

Is there any asynchronous Python ORM other than Twistar?

I'm looking for lightweight ORM for non-blocking API, built on top of tornado. Of course, I can write raw SQL queries using momoko, but I'd like to work with objects.


Source: (StackOverflow)

Tornado login Examples/Tutorials [closed]

I was wondering if anyone know of any example code or tutorials on implementing a login/signup page in Tornado? Ive seen the examples that come with it, but they seem very facebook/oauth centric.


Source: (StackOverflow)

How to best perform Multiprocessing within requests with the python Tornado server?

I am using the I/O non-blocking python server Tornado. I have a class of GET requests which may take a significant amount of time to complete (think in the range of 5-10 seconds). The problem is that Tornado blocks on these requests so that subsequent fast requests are held up until the slow request completes.

I looked at: https://github.com/facebook/tornado/wiki/Threading-and-concurrency and came to the conclusion that I wanted some combination of #3 (other processes) and #4 (other threads). #4 on its own had issues and I was unable to get reliable control back to the ioloop when there was another thread doing the "heavy_lifting". (I assume that this was due to the GIL and the fact that the heavy_lifting task has high CPU load and keeps pulling control away from the main ioloop, but thats a guess).

So I have been prototyping how to solve this by doing "heavy lifting" tasks within these slow GET requests in a separate process and then place a callback back into the Tornado ioloop when the process is done to finish the request. This frees up the ioloop to handle other requests.

I have created a simple example demonstrating a possible solution, but am curious to get feedback from the community on it.

My question is two-fold: How can this current approach be simplified? What pitfalls potentially exist with it?

The Approach

  1. Utilize Tornado's builtin asynchronous decorator which allows a request to stay open and for the ioloop to continue.

  2. Spawn a separate process for "heavy lifting" tasks using python's multiprocessing module. I first attempted to use the threading module but was unable to get any reliable relinquishing of control back to the ioloop. It also appears that mutliprocessing would also take advantage of multicores.

  3. Start a 'watcher' thread in the main ioloop process using the threading module who's job it is to watch a multiprocessing.Queue for the results of the "heavy lifting" task when it completes. This was needed because I needed a way to know that the heavy_lifting task had completed while being able to still notify the ioloop that this request was now finished.

  4. Be sure that the 'watcher' thread relinquishes control to the main ioloop loop often with time.sleep(0) calls so that other requests continue to get readily processed.

  5. When there is a result in the queue then add a callback from the "watcher" thread using tornado.ioloop.IOLoop.instance().add_callback() which is documented to be the only safe way to call ioloop instances from other threads.

  6. Be sure to then call finish() in the callback to complete the request and hand over a reply.

Below is some sample code showing this approach. multi_tornado.py is the server implementing the above outline and call_multi.py is a sample script that calls the server in two different ways to test the server. Both tests call the server with 3 slow GET requests followed by 20 fast GET requests. The results are shown for both running with and without the threading turned on.

In the case of running it with "no threading" the 3 slow requests block (each taking a little over a second to complete). A few of the 20 fast requests squeeze through in between some of the slow requests within the ioloop (not totally sure how that occurs - but could be an artifact that I am running both the server and client test script on the same machine). The point here being that all of the fast requests are held up to varying degrees.

In the case of running it with threading enabled the 20 fast requests all complete first immediately and the three slow requests complete at about the same time afterwards as they have each been running in parallel. This is the desired behavior. The three slow requests take 2.5 seconds to complete in parallel - whereas in the non threaded case the three slow requests take about 3.5 seconds in total. So there is about 35% speed up overall (I assume due to multicore sharing). But more importantly - the fast requests were immediately handled in leu of the slow ones.

I do not have a lot experience with multithreaded programming - so while this seemingly works here I am curious to learn:

Is there a simpler way to accomplish this? What monster's may lurk within this approach?

(Note: A future tradeoff may be to just run more instances of Tornado with a reverse proxy like nginx doing load balancing. No matter what I will be running multiple instances with a load balancer - but I am concerned about just throwing hardware at this problem since it seems that the hardware is so directly coupled to the problem in terms of the blocking.)

Sample Code

multi_tornado.py (sample server):

import time
import threading
import multiprocessing
import math

from tornado.web import RequestHandler, Application, asynchronous
from tornado.ioloop import IOLoop


# run in some other process - put result in q
def heavy_lifting(q):
    t0 = time.time()
    for k in range(2000):
        math.factorial(k)

    t = time.time()
    q.put(t - t0)  # report time to compute in queue


class FastHandler(RequestHandler):
    def get(self):
        res = 'fast result ' + self.get_argument('id')
        print res
        self.write(res)
        self.flush()


class MultiThreadedHandler(RequestHandler):
    # Note:  This handler can be called with threaded = True or False
    def initialize(self, threaded=True):
        self._threaded = threaded
        self._q = multiprocessing.Queue()

    def start_process(self, worker, callback):
        # method to start process and watcher thread
        self._callback = callback

        if self._threaded:
            # launch process
            multiprocessing.Process(target=worker, args=(self._q,)).start()

            # start watching for process to finish
            threading.Thread(target=self._watcher).start()

        else:
            # threaded = False just call directly and block
            worker(self._q)
            self._watcher()

    def _watcher(self):
        # watches the queue for process result
        while self._q.empty():
            time.sleep(0)  # relinquish control if not ready

        # put callback back into the ioloop so we can finish request
        response = self._q.get(False)
        IOLoop.instance().add_callback(lambda: self._callback(response))


class SlowHandler(MultiThreadedHandler):
    @asynchronous
    def get(self):
        # start a thread to watch for
        self.start_process(heavy_lifting, self._on_response)

    def _on_response(self, delta):
        _id = self.get_argument('id')
        res = 'slow result {} <--- {:0.3f} s'.format(_id, delta)
        print res
        self.write(res)
        self.flush()
        self.finish()   # be sure to finish request


application = Application([
    (r"/fast", FastHandler),
    (r"/slow", SlowHandler, dict(threaded=False)),
    (r"/slow_threaded", SlowHandler, dict(threaded=True)),
])


if __name__ == "__main__":
    application.listen(8888)
    IOLoop.instance().start()

call_multi.py (client tester):

import sys
from tornado.ioloop import IOLoop
from tornado import httpclient


def run(slow):
    def show_response(res):
        print res.body

    # make 3 "slow" requests on server
    requests = []
    for k in xrange(3):
        uri = 'http://localhost:8888/{}?id={}'
        requests.append(uri.format(slow, str(k + 1)))

    # followed by 20 "fast" requests
    for k in xrange(20):
        uri = 'http://localhost:8888/fast?id={}'
        requests.append(uri.format(k + 1))

    # show results as they return
    http_client = httpclient.AsyncHTTPClient()

    print 'Scheduling Get Requests:'
    print '------------------------'
    for req in requests:
        print req
        http_client.fetch(req, show_response)

    # execute requests on server
    print '\nStart sending requests....'
    IOLoop.instance().start()

if __name__ == '__main__':
    scenario = sys.argv[1]

    if scenario == 'slow' or scenario == 'slow_threaded':
        run(scenario)

Test Results

By running python call_multi.py slow (the blocking behavior):

Scheduling Get Requests:
------------------------
http://localhost:8888/slow?id=1
http://localhost:8888/slow?id=2
http://localhost:8888/slow?id=3
http://localhost:8888/fast?id=1
http://localhost:8888/fast?id=2
http://localhost:8888/fast?id=3
http://localhost:8888/fast?id=4
http://localhost:8888/fast?id=5
http://localhost:8888/fast?id=6
http://localhost:8888/fast?id=7
http://localhost:8888/fast?id=8
http://localhost:8888/fast?id=9
http://localhost:8888/fast?id=10
http://localhost:8888/fast?id=11
http://localhost:8888/fast?id=12
http://localhost:8888/fast?id=13
http://localhost:8888/fast?id=14
http://localhost:8888/fast?id=15
http://localhost:8888/fast?id=16
http://localhost:8888/fast?id=17
http://localhost:8888/fast?id=18
http://localhost:8888/fast?id=19
http://localhost:8888/fast?id=20

Start sending requests....
slow result 1 <--- 1.338 s
fast result 1
fast result 2
fast result 3
fast result 4
fast result 5
fast result 6
fast result 7
slow result 2 <--- 1.169 s
slow result 3 <--- 1.130 s
fast result 8
fast result 9
fast result 10
fast result 11
fast result 13
fast result 12
fast result 14
fast result 15
fast result 16
fast result 18
fast result 17
fast result 19
fast result 20

By running python call_multi.py slow_threaded (the desired behavior):

Scheduling Get Requests:
------------------------
http://localhost:8888/slow_threaded?id=1
http://localhost:8888/slow_threaded?id=2
http://localhost:8888/slow_threaded?id=3
http://localhost:8888/fast?id=1
http://localhost:8888/fast?id=2
http://localhost:8888/fast?id=3
http://localhost:8888/fast?id=4
http://localhost:8888/fast?id=5
http://localhost:8888/fast?id=6
http://localhost:8888/fast?id=7
http://localhost:8888/fast?id=8
http://localhost:8888/fast?id=9
http://localhost:8888/fast?id=10
http://localhost:8888/fast?id=11
http://localhost:8888/fast?id=12
http://localhost:8888/fast?id=13
http://localhost:8888/fast?id=14
http://localhost:8888/fast?id=15
http://localhost:8888/fast?id=16
http://localhost:8888/fast?id=17
http://localhost:8888/fast?id=18
http://localhost:8888/fast?id=19
http://localhost:8888/fast?id=20

Start sending requests....
fast result 1
fast result 2
fast result 3
fast result 4
fast result 5
fast result 6
fast result 7
fast result 8
fast result 9
fast result 10
fast result 11
fast result 12
fast result 13
fast result 14
fast result 15
fast result 19
fast result 20
fast result 17
fast result 16
fast result 18
slow result 2 <--- 2.485 s
slow result 3 <--- 2.491 s
slow result 1 <--- 2.517 s

Source: (StackOverflow)

Using a simple python generator as a co-routine in a Tornado async handler?

I have a python generator function which yields chunks of text. I would like to write a get method for a tornado.web.RequestHandler subclass that will iterate over the generator, writing the chunks out to the response as it goes.

Since this is Tornado, and since the generator may take over a second to process, I thought it would be nice to make the handler asynchronous, using this generator as a co-routine and passing off control to the IOLoop after every chunk. However, I can't make heads or tails of how to do this.

Here's my example (blocking) code:

class TextHandler(web.RequestHandler):
    @web.asynchronous
    def get(self, n):
        generator = self.generate_text(100000)
        # Clearly, this will block. How to make it asynchronous?
        for text in generator:
            self.write(text)

    def generate_text(n):
        for x in xrange(n):
            if not x % 15:
                yield "FizzBuzz\n"
            elif not x % 5:
                yield "Buzz\n"
            elif not x % 3:
                yield "Fizz\n"
            else:
                yield "%s\n" % x

How can I make this handler work asynchronously?


Source: (StackOverflow)

How do I get the client IP of a Tornado request?

I have a RequestHandler object for incoming post()s. How can I find the IP of the client making the request? I've browsed most of RequestHandler's methods and properties and seem to have missed something.


Source: (StackOverflow)

What are the possible ways to authenticate user when websocket connection is used?

Example scenario: Web based multi-user chat application through websocket connection. How can I ensure (or guarantee) that each connection in this application belongs to certain authenticated user and "can't be" exploited by false user impersonation or intervene during the connection.

by the way I am using tornado websocket on server side to implement basic chat room and already doing authentication for the non-websocket part of my app.

ps : suppose authenticated user posts what he wants and when other user open the listing page of item and automatically other user is added to list of websocket listeners what I want each user able to chat with buyer of the item individually not in a chatroom way but with one to one chat


Source: (StackOverflow)

Is 'epoll' the essential reason that Tornadoweb(or Nginx) is so fast?

Tornadoweb and Nginx are popular web servers for the moment and many benchmarkings show that they have a better performance than Apache under certain circumstances. So my question is:

Is 'epoll' the most essential reason that make them so fast? And what can I learn from that if I want to write a good socket server?


Source: (StackOverflow)

tornado 403 GET warning when opening websocket

I found this python script which should allow me to open a websocket. However, I receive the warning [W 1402720 14:44:35 web:1811] 403 GET / (192.168.0.102) 11.02 ms in my linux terminal when trying to open the actual websocket (using Old WebSocket Terminal Chrome plugin). The messages "connection opened", "connection closed" and "message received" are never printed in the terminal window.

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket

class MyHandler(tornado.websocket.WebSocketHandler):
        def open(self):
                print "connection opened"
                self.write_message("connection opened")

        def on_close(self):
                print "connection closed"

        def on_message(self,message):
                print "Message received: {}".format(message)
                self.write_message("message received")

if __name__ == "__main__":
        tornado.options.parse_command_line()
        app = tornado.web.Application(handlers=[(r"/",MyHandler)])
        server = tornado.httpserver.HTTPServer(app)
        server.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

Source: (StackOverflow)

What is Facebook's new Tornado framework?

Facebook just open-sourced a framework called Tornado.

What is it? What does it help a site do?

I believe Facebook uses a LAMP structure. Is it useful for smaller sites which are written under the LAMP stack?


Source: (StackOverflow)

Tornado on Raspberry Pi to use websockets as well as monitor serial port Arduino communication

Essentially, what I'm hoping to achieve is a canvas based web interface to control an Arduino, via a Raspberry Pi. The use case is that a user navigates to raspberrypi:8080 which displays a canvas. Then upon moving a slider, a websocket message is sent to the Tornado server on the Raspberry Pi. Tornado then sends a serial message to the Arduino which changes the RGB value of an LED. So far so good, I've been able to do this with the help of the documentation by a developer, Raspberry Pi Android HTML5 Realtime Servo Control.

However, the communication is only one-way from Raspberry Pi to Arduino. I'd like Tornado to also monitor the serial port to get any sensor data back to the front-end. Here's where I'm unsure about how to proceed. I was able to accomplish something like this using Node.js, which monitors for both websocket messages as well as serial messages asynchronously.

Should an asynchronous process be spawned which constantly monitors the port? I've seen a couple of options for this sort of solution.

  1. Some people suggest tornado.gen.Task, but for single HTTP requests, not for constant serial data.
  2. tornado.ioloop.PeriodicCallback which I could set up to check for serial data every millisecond, but that sounds like a lot of overhead.
  3. I've also seen separate tools such as Swirl. (Swirl is outdated according to it's Github repo)

Or should I set up a separate Python application which monitors serial and then communicates to the Tornado application on something it can understand like the following?

  1. websocket messages using a websocket client
  2. ZeroMQ (working example: pyzmq / examples / eventloop / web.py)

So there are lots of options... What are some recommendations and some reasons to try out or avoid any of the above options?

Here's what I have and need to add serial monitoring to:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket

from tornado.options import define, options
define("port", default=8080, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('index.html')

class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print 'new connection'
        self.write_message("connected")

    def on_message(self, message):
        print 'message received %s' % message
        self.write_message('message received %s' % message)

    def on_close(self):
        print 'connection closed'

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[
            (r"/", IndexHandler),
            (r"/ws", WebSocketHandler)
        ]
    )
    httpServer = tornado.httpserver.HTTPServer(app)
    httpServer.listen(options.port)
    print "Listening on port:", options.port
    tornado.ioloop.IOLoop.instance().start()

Source: (StackOverflow)

How use Django with Tornado web server?

How do I use Django with the Tornado web server?


Source: (StackOverflow)

In tornado is it possible to return a HTTP error code without the default template?

I am currently using the following to raise a HTTP bad request:

raise tornado.web.HTTPError(400)

which returns a html output:

<html><title>400: Bad Request</title><body>400: Bad Request</body></html>

Is it possible to return just the HTTP response code with a custom body?


Source: (StackOverflow)

How to run functions outside websocket loop in python (tornado)

I'm trying to set up a small example of a public Twitter stream over websockets. This is my websocket.py, and it's working.

What I'm wondering is: how can I interact with the websocket from 'outside' the class WSHandler (ie. not only answer when receiving a message from websocket.js)? Say I want to run some other function within this same script that would post "hello!" every five seconds and send that to the websocket (browser) without any interaction from client-side. How could I do that?

So it's kind of a fundamental beginner's question, I suppose, about how to deal with classes as those below. Any pointers in any direction would be greatly appreciated!

import os.path
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web

# websocket
class FaviconHandler(tornado.web.RequestHandler):
    def get(self):
        self.redirect('/static/favicon.ico')

class WebHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("websockets.html")

class WSHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print 'new connection'
        self.write_message("Hi, client: connection is made ...")

    def on_message(self, message):
        print 'message received: \"%s\"' % message
        self.write_message("Echo: \"" + message + "\"")
        if (message == "green"):
            self.write_message("green!")

    def on_close(self):
        print 'connection closed'



handlers = [
    (r"/favicon.ico", FaviconHandler),
    (r'/static/(.*)', tornado.web.StaticFileHandler, {'path': 'static'}),
    (r'/', WebHandler),
    (r'/ws', WSHandler),
]

settings = dict(
    template_path=os.path.join(os.path.dirname(__file__), "static"),
)

application = tornado.web.Application(handlers, **settings)

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

Source: (StackOverflow)

Tornado URL query parameters

I've been playing around with Tornado, and I've written some code that doesn't seem very nice.

I'm writing an app to store recipes as an example. These are my handlers:

handlers = [
    (r"/recipes/", RecipeHandler),
    (r"/recipes", RecipeSearchHandler), #so query params can be used to search
]

This lead me to writing this:

class RecipeHandler(RequestHandler):      
    def get(self):
        self.render('recipes/index.html')

class RecipeSearchHandler(RequestHandler):    
    def get(self):
        try:
            name = self.get_argument('name', True)
            self.write(name)
        # will do some searching
        except AssertionError:
            self.write("no params")
            # will probably redirect to /recipes/

Is there a better way to approach these URLs without a try/except? I'd like /recipes and /recipes/ to show the same thing, whereas /recipes?name=something would do a search, and ideally be a different handler.


Source: (StackOverflow)

Is Tornado really non-blocking?

Tornado advertises itself as "a relatively simple, non-blocking web server framework" and was designed to solve the C10k problem. However, looking at their database wrapper, which wraps MySQLdb, I came across the following piece of code:

def _execute(self, cursor, query, parameters):
    try:
        return cursor.execute(query, parameters)
    except OperationalError:
        logging.error("Error connecting to MySQL on %s", self.host)
        self.close()
        raise

As far as I know calls to the MySQLdb, which is built on top of libmysqlclient, are blocking.

Am I right in thinking that a long-running query would render the entire Tornado server unresponsive until it finishes or is there magic on the code?


Source: (StackOverflow)