## Stormy Webber
Wes Mason
[@1stvamp](http://twitter.com/1stvamp)
## Who?
- / `@1stvamp`
- Online services, [Canonical](http://www.canonical.com/)
- Open source
## Tornado
- Fast web server that supports non-blocking I/O
- Developed at FriendFeed, open sourced at Facebook in 2009
- Long polling, WebSockets etc.
- Pure Python
## Tornado cont.
- **Not** a framework.
- Usual "framework" features, sessions, auth, templates etc.
- Support for callbacks, coroutines and futures (Tulip*ish*)
## Asynchronous
- Asynchronous != parallel
- Cooperative "threading" via callbacks and coroutines
- Non-blocking I/O, both HTTP client/server built in
## Stringing cats
- `ioloop.add_callback`, `ioloop.add_future`
- `gen.coroutine`, `gen.Task`, `gen.Wait`
## e.g.
```
result = yield motor.Op(db.messages.insert, {'msg': msg})
# vs.
db.messages.insert(
{'msg': msg},
callback=self._on_response)
```
## Great for RESTful webservices
## e.g.
```
import tornado.web
from sys import exit
from .handlers import ResourceHandler
def main():
application = tornado.web.Application((
(r"/resources/", ResourceHandler, "resources-root")
),)
application.listen(port=8888, address='0.0.0.0')
return tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
exit(main())
```
## e.g.
```
import time
from tornado.web import asynchronous, RequestHandler
class ResourceHandler(RequestHandler):
def prepare(self):
self.user_id = self.get_argument('user')
@asynchronous
def get(self):
tornado.ioloop.IOLoop.instance().add_timeout(
time.time()+60, self._end)
def _end(self):
self.finish('hello world!')
```
## Best tool for the job
- Can be mixed freely with other libraries
- Mostly useful if there is an async library available for your backend component
- If you want socket.io support gevent has a better library etc.
## Batteries included
- Templating, auth handlers (including Twitter OAuth `LOL`)
- HTTP client / server
- TCP client / server (Streams)
## Batteries included cont.
- Thread pools
- Async DNS (`c-ares`, threads, `TwistedResolver`)
- Process pooling with bound master socket/port
## Batteries included cont.
- `tornado.platform.twisted`
- WebSockets / Longpolling
- SMTP client
## Bonus & tricks
- Coroutines can be wrapped with greenlets (tornalet)
- pycurl and libcurl are **fast**
- Support for Futures (PEP 3156)
- It runs on pypy, extremely fast
## trequests
- Use libraries that use `python-requests` for HTTP
- Use Tornado's AsyncHTTPClient/CurlAsyncHTTPClient instead of `httplib3`
- Caveat: does require `greenlet`
## trequests cont.
```
"""bobs_big_data.py"""
import requests
class BigData(object):
...
def post(self):
r = requests.post(self.url, data=self.data)
return r.json()
```
## trequests cont.
```
import bobs_big_data
from tornado.web import RequestHandler
from trequests import setup_session
from tornalet import tornalet
setup_session()
class WebHandler(RequestHandler):
@tornalet
def get(self):
data = {'foo': 'bar'}
response = bobs_big_data.BigData(data).post()
return self.write(response)
```
## trequests cont.
[github.com/1stvamp/trequests](https://github.com/1stvamp/trequests/)
## sys.exit(0)
- Slides: [github.com/1stvamp/stormy-webber](https://github.com/1stvamp/stormy-webber)
## ^D
- Jonathan "Joff" Oliver: [about.me/joffie](http://about.me/joffie)
- Grab me and say hi `:-)`