The Beauty of Eventlet

Here’s a nice little article about using node.js to implement a port forwarder.  The two Python examples he cited were butt-ugly (actually, he linked to one butt-ugly example twice accidentally).  Surely we can make Python look better!

from eventlet.green import socket
import eventlet
def callback():
    print "called back"

def forward(source, dest, cb = lambda: None):
    while True:
        d = source.recv(1024)
        if d == '':
            cb()
            break
        dest.sendall(d)

listener = socket.socket()
listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
listener.bind(('localhost', 7000))
listener.listen(500)
while True:
    client, addr = listener.accept()
    server = socket.create_connection(('localhost', 22))
    eventlet.spawn_n(forward, client, server, callback)
    eventlet.spawn_n(forward, server, client)

To me that seems a little bit more readable than the node.js version, and it’s a little bit shorter, as well.  I’m particularly happy about how the forward function is used bidirectionally, so there’s no duplication of that logic.  Thanks to Eventlet, it’s just as scalable as node.js; you could connect thousands of clients to this thing.

2 responses to this post.

  1. Hey,

    Your eventlet example does look good. Regarding being more readable than node.js solution, I would say that’s highly subjective. I still find the node.js example more readable because that shields me from low level socket fiddling.

    I am not too sure about being as scalable as node.js. node.js runs on V8, uses optimized event libraries and runs code close to the iron compared to python’s bytecodes. There are a couple of benchmarks where node.js has out-performed Twisted and Tornado. Unfortunately, I couldn’t find the links. I would try to benchmark my solution and yours. Let me know if you have done any benchmarking.

    PS: I fixed the python solution links.

  2. Posted by Which Linden on February 11, 2010 at 9:13 pm

    Agh! WordPress filtered your comment as “spam” for some reason, had to dig it out! :/

    That’s an interesting point you bring up about scalability. Eventlet also uses optimized event libraries (libevent), so it’s probably a tie there. The biggest problem, as I understand it, is that CPython is actually slower than V8, per this shootout link: http://shootout.alioth.debian.org/u64/benchmark.php?test=all&lang=v8&lang2=python That’s lame, and it basically means that *any* Python-based library is going to be slower than a V8-based one, just right off the bat. Haven’t tried any benchmarking of this particular application myself.

    As to readability, yes, not fiddling with sockets is nice (and there are some conveniences to get around this to some degree that I didn’t use), but for me the biggest question is whether to have callback functions or not; a while loop makes the control flow a lot clearer to my eye. This becomes more of a factor with applications that are more complex than this simple example. But, I definitely agree that it’s subjective; some people really like thinking in terms of piles of callbacks, some people don’t!

Respond to this post