fibers: lightweight cooperative microthreads for Python

Hi all!

Today I’m really happy to share the first version of fibers, a project I’ve working on for a while.

Fibers are lightweight primitives for cooperative multitasking in Python. They provide means for running pieces of code that can be paused and resumed. Unlike threads, which are preemptively scheduled, fibers are scheduled cooperatively, that is, only one fiber will be running at a given point in time, and no other fiber will run until the user explicitly decides so.

When a fiber is created it will not run automatically. A fiber must be ‘switched’ into for it to run. Fibers can switch control to other fibers by way of the switch or throw functions, which switch control or raise and exception in the target fiber respectively.

 

This project is heavily inspired by greenlet, as you may have noticed. I’ve been using greenlet for a long while, but for a recent project I’ve worked on, I wanted to offer an interface similar to the Thread class from the threading module. Unfortunately the API in greenlet didn’t make it easy, so I took it as an excuse to try to build the library I wanted to use, which hopefully also helps others.

The obvious step would have been to fork greenlet itself and change the API to my needs, but I randomly ran into stacklet, a tiny library hidden in the PyPy source code, which is used as the base for the greenlet implementation in PyPy.

So, I stood on shoulders of giants and built fibers using stacklet. It solves my problems, hopefully it can help you too! In case you are interested in a more verbose version of the project rationale, I added a specific section in the documentation.

The source code is available on GitHub, with MIT license, enjoy!

import fibers

def runner(*args, **kw):
    print "hello, I'm running inside a fiber! - %r" % fibers.current()

f = fibers.Fiber(target=runner)
f.switch()

:wq

pyuv 0.10.5 (stable) and 0.11.0 (unstable) released!

I’m happy to announce two new pyuv releases today: pyuv 0.10.5 (stable) and 0.11.0 (unstable). Why two releases? For those who may not know, pyuv follows the NodeJS release cycle, that is, odd numbered releases are the so called “unstable” releases, while the even numbered releases are “stable”.

The 0.10.5 release brings  few bugfixes and embeds the latest version of libuv, so you also benefit from the bugfixes in libuv.

pyuv 0.11.0 includes some heavy refactoring of the filesystem operations, which unfortunately are not backwards compatible, but I hope it’s for the best:

In pyuv 0.10x this is the way to stat a file asynchronously:

def cb(loop, path, result, error):
    if error is None:
        print result
    # ...

pyuv.fs.stat(loop, 'test.py', callback=cb)

And here is the equivalent in pyuv 0.11:

def cb(req):
    if req.error is None:
        print result
    # ...

req = pyuv.fs.stat(loop, 'test.py', callback=cb)

All filesystem operations now get a single argument in the callback: the FSRequest object which was returned to the caller when the function was initially called. The loop, path, result and error are now attributes of the request object. Moreover, the request object now has an instance dictionary, so you can attach any attribute to it and use it later:

def cb(req):
    assert req.foo == 'foo'
    if req.error is None:
        print result
    # ...

req = pyuv.fs.stat(loop, 'test.py', callback=cb)
req.foo = 'foo'

There have been other big internal changes due to changes in libuv itself, but those are not visible in pyuv since it provides a class-level abstraction.

The next stable release will be pyuv 0.12.0, right when Node 0.12 is launched. Until then 0.10 will remain as the stable branch, and the one installable through PyPI, those of you interested in the latest and the greatest, go fetch master on GitHub 🙂

:wq

 

Serving a WSGI app, WebSockets and static files with Twisted

Long time no post! Lets solve that now shall we?

A few days ago I started playing a bit with Flask, since I’m considering it as the framework to build some API server. I have no web development experience, and Flask looks like a great project so I went with that.

I started with a tiny little hello world, and then I wanted to add some websockets and some CSS. Oh the trouble. When I started looking for how to combine a Flask app with WebSockets I found references to gevent-socketio for the most part, but I somewhat wanted to use Twisted this time, so I kept looking. Soon enough I found AutoBahn, a great WebSocket implementation for Twisted, which can be combined with a WSGI app, brilliant! After seeing how AutoBahn manages to add the websocket route to the WSGI app, adding support for static files was kind of trivial.

Here is the result of my experiments, a really simple web app which consists of a Flask WSGI app, a WebSocket server and some static files, all served by the same process running Twisted. You may not want to do this in a production environment, but hey, I’m just playing here 🙂

[gist]https://gist.github.com/saghul/5961882[/gist]

Since Gist does not currently allow folders, make sure you keep this layout after downloading the files:

├── app.py
├── settings.py
└── templates
    ├── assets
    │   └── style.css
    └── index.html

We’ll use the twistd command line tool to launch out application, since it can take care of logging, running as a daemon, etc. To run it in the foreground:

twistd -n -l - -y app.py

This will launch the application in non-daemon mode and log to standard output.

Hope this helps someone, all feedback is more than welcome 🙂

:wq

Evergreen 0.0.4 released!

It’s been a while since I haven’t posted around here! I made a few evergreen releases which are probably worth mentioning. They are pretty minor, no big changes have happened. The module which got most of the work is the io module, which I expect to improve more, as well as add cooperative UDP, TLS and file I/O support.

In addition, I created a couple of packages extending evergren’s functionality:

If you are using evergeen, let me know! Hopefully I can continue to make it better bit by bit.

:wq

 

Evergreen: cooperative multitasking and i/o for Python

I’ve been working on-and-off on this project for almost a year during my free time, and after meditating about it I thought: “fuck it, ship it”. Allow me to introduce Evergreen: cooperative multitasking and i/o for Python.

“So, another framework?” I hear you say. Yes, it’s another async framework. But it’s my async framework. I’ve used a number of frameworks for developing servers in Python such as Twisted, Tornado, Eventlet, Gevent and lately Tulip and all of them have great and not so great things, so I decided to blend the ideas I gathered from all of them, add some opinionated decisions, some Stackless flavour and Evergreen was the result.

standards

Evergreeen is a framework which allows developers to write synchronous looking code which is executed asynchronously in a cooperative manner. Evergreen presents an API which looks like the one you would use to write concurrent programs using threads or futures from the Python standard library. The facilities provided by Evergreen are however cooperative, that is, while a task is busy waiting for some i/o other tasks will have their chance to run.

“Show me the code!” I hear you say. Sure, it’s up here on GitHub, released under the MIT license. Since the usual example is a web crawler, here you have one.

Did I mention it supports Python 2 and 3?

“Is it production ready?” I hear you say. It’s still on a very early stage, but I believe the foundation is solid. However, the APIs provided by Evergreen may change a bit until I feel confortable with them. All feedback is welcome, so if you give it a try do let me know!

I’d like to thank all authors of similar libraries for releasing their work as Open Source which I could look into and learn from.

I hope Evergreen can help you solve some problems and you enjoy using it as much as I do developing it.

:wq

 

pyuv 0.10.0 relased!

Today I’m happy to announce that pyuv 0.10.0 has been released! Following libuv’s versioning, this is a stable release, that is, no API changes will occur during the 0.10.x branch cycle.

It has been a while since the last stable release, there have been many changes, even though not all of them are directly visible in the public API. Here is a short list of the most relevant changes for version 0.10.0 since the 0.8 series:

  • Added a true signal watcher
  • Added ability to handle uncaught exceptions (Loop.excepthook)
  • Added TCP.open and UDP.open methods
  • Added support for compilation with Visual Studio in Windows
  • Added thread module with several thread synchronization primitives
  • Added mode parameter to Loop.run (default, once or nowait)
  • Added fileno and get_timeout methods to Loop
  • Added ability to cancel threadpool, getaddrinfo and fs requests
  • Added ability to stop the event loop (Loop.stop)
  • Moved getaddrinfo to util module
  • Removed builtin c-ares resolver
  • Removed get/set process title functions
  • Fixed numerous refcounting issues
  • Multiple fixes for Windows
  • Multiple memory related internal optimizations

There are many more changes, all listed in the changelog file.

I’m glad to say that pyuv is now in better shape than it ever has been. Not only because I have learned many things along the way, but also because I got really good pull requests and help which enhanced pyuv in many different ways. I’m not a Windows guy and got invaluable help from people which helped make pyuv work properly on Windows. Releases 0.9.5-6 contain more commits from others than from myself, and I love that!

Last, I’d like to thank the libuv core team, more specifically Ben and Bert. They do a great job both coding libuv itself and helping others get involved in the project. This is one of the projects I’m really happy I contribute to. Oh, I also scored 4th in the libuv contributions (in lines of code) for Node 0.10.0!

You can get the source code at the usual place, and check the updated documentation here.

Rose: a PEP-3156 compatible event loop based on pyuv

For those who don’t know, PEP 3156 is a proposal for asynchronous I/O in Python, starting with Python 3.3. Until now each framework (Twisted, Tornado, …) has defined it’s own interface for defining protocols and transports. This makes very difficult if not impossible to reuse a protocol implementation across frameworks. PEP 3156 tries to fix that, among other things.

The reference implementation is called Tulip and can be found here. It’s a fast moving target, but it already contains working event loops for Windows and Unix systems. It uses pollers available in the select module for the Unix side, and a C module wrapping Windows IOCP functionality for Windows.

I was really excited to see this come through, so I started playing with it by implementing a pyuv based event loop. I called that it rose. It was a lot easier to implement than expected and it currently passes the entire test suite 🙂

Code can be found on GitHub.

Here is a quick example, the usual echo server, using rose and tulip:

[gist]https://gist.github.com/saghul/4718429[/gist]

Come and join the discussion in the python-ideas mailing list!

:wq

How do event loops work in Python?

I had the pleasure to give a presentation at the first ever Python Devroom at FOSDEM. I talked about how event loops work internally and how pyuv can help by abstracting a lot of the problems with a pretty simple to use API. I also introduced rose, a pyuv based PEP-3156 event loop implementation, but I’ll write a followup post on that 🙂

Thanks a lot to everyone who attended the talk, and for those who couldn’t here are the slides!

[slideshare id=16349302&doc=howdoeventloopswork-130204164956-phpapp01]

:wq

TLS connections with pyuv and pyOpenSSL

Those of you who have been following the pyuv and/or libuv libraries may have run into this at some point: “how do I use TLS with this”? pyuv provides something similar to a socket with a completion style interface, but it only does TCP. There is also the Poll handle, which can be used to use a regular Python socket with pyuv.

Of course, this second approach is the quickest/easiest in order to get TLS working, because the Python sockets already have TLS support thanks to the ssl module. I wanted to experiment with adding some sort of TLS handle, in the same fashion as the TCP handle, that is, not with regular Python sockets.

There are 2 main libraries providing TLS support (in general): OpenSSL and GnuTLS. What I basically wanted to do was encrypt/decrypt the data in memory and read/write it to a pyuv TCP handle. OpenSSL has this functionality through the BIO API, but I didn’t see anything similar in GnuTLS at a first glance so I went with OpenSSL.

I created a quick TLS handle with the ideas expressed above, it can be found in this gist.

It contains the TLS handle, example echo server and client and some sample certificates. Here is the client implementation sample, for the rest check the full gist.

[gist]https://gist.github.com/4599831[/gist]

It’s pretty basic, but I hope it serves as a starting point for using pyuv with TLS. I plan to analyze the performance compared to regular Python sockets in another blog post.

:wq

greenlet local storage on greenlet 0.4.0

Greenlet 0.4.0 brought an interesting new feature: an instance dictionary on each greenlet object, which makes it a lot simpler to implement greenlet local storage. Here is how greenlet local storage is currently implemented in Eventlet and in Gevent.

As it can be seen, the implementation is not particularly straightforward, mainly due to the fact that the actual information needs to be stored in a separate entity and mapped to each greenlet.

Thanks to the instance dictionary added in 0.4.0, we can use some attribute in it to keep the locally stored objects. The plan is to use a dictionary called __local_dict__ and store the greenlet local attributes there. Here is how it looks like:

[gist]https://gist.github.com/4151154[/gist]

Hope it’s of use.

:wq