Inspired by StackOverflow question:
If it won't be simple, it simply won't be. [Hire me, source code] by Miki Tebeka, CEO, 353Solutions
Monday, July 23, 2012
Saturday, July 07, 2012
Show Dependecies of Azkaban Jobs
We're using Azkaban at work to schedule Hadoop jobs.
It's hard to view the job dependencies without deploying, so here's a little script that will show you job dependencies as an image. It uses dot (from Graphviz) to produce the image.
Tuesday, June 26, 2012
Python Based Assembler
Got reminded of a project I did while back. It's a Python based assembler. The main idea is that the assembly file is actually a Python file with pre-set functions (assembly instruction).
In this manner, I managed to skip lexing, parsing and other things and deliver a working assembler in two days.
You can view the presentation I gave on this here.
The Assembler
Example Input
Friday, May 04, 2012
Using travis-ci with bitbucket
travis-ci is a great service. My problem is that it works only with github while I mainly use bitbucket (and please, let's not get into hg/git debate - hg is way better :).
The way I found to make this work is to mirror my bitbucket projects on github using hg-git. Below is an example from fastavro.
First, you need to install hg-git. It's available from PyPI, "pip install hg-git" will do the trick, (or "easy_install hg-git" if you don't have pip).
Then create a repository on github to mirror the one on bitbucket. After that tell travis-ci to watch this repository.
Next step is to enable hg-git in your repository, edit .hg/hgrc and add the following:
Then "bootstrap" it with the following command:
Next step is to create .travis.yml, For fastavro I have both Python 2.7 and 3.2.
Last step, is to make sure every time we push to bitbucket, changes are pushed to github as well. This is done with an outgoing hook in .hg/hgrc
(The || true is there since hg push will exit with non-zero value sometimes)
That's all. Now fastavro has continuous integration that runs both on Python 2.7 and 3.2.
The way I found to make this work is to mirror my bitbucket projects on github using hg-git. Below is an example from fastavro.
First, you need to install hg-git. It's available from PyPI, "pip install hg-git" will do the trick, (or "easy_install hg-git" if you don't have pip).
Then create a repository on github to mirror the one on bitbucket. After that tell travis-ci to watch this repository.
Next step is to enable hg-git in your repository, edit .hg/hgrc and add the following:
[extensions] hgext.bookmarks = hggit =
Then "bootstrap" it with the following command:
hg bookmark -r default master
Next step is to create .travis.yml, For fastavro I have both Python 2.7 and 3.2.
Last step, is to make sure every time we push to bitbucket, changes are pushed to github as well. This is done with an outgoing hook in .hg/hgrc
[hooks] outgoing = hg push git+ssh://git@github.com/tebeka/fastavro.git || true
(The || true is there since hg push will exit with non-zero value sometimes)
That's all. Now fastavro has continuous integration that runs both on Python 2.7 and 3.2.
Monday, April 23, 2012
Twitter Post Frequency
Sometime I see interesting new people on Twitter. However before adding them I'd like to know what is their post frequency so I won't get spammed.
Below is a simple script to do that:
Tuesday, March 27, 2012
A lambda Gotcha
Quick, what is the output of the following?
The right answer is:
This is due to the fact that i is bound to the same variable in all the lambdas, and has the final value of 9.
There are two ways to overcome this. The first is to use the fact the default arguments are evaluated at function creation time (which is another known gotcha).
In [3]: callbacks = [lambda i=i: i for i in range(10)]
In [4]: [c() for c in callbacks]
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The second is to create a function generator function:
In [5]: def make_callback(i):
...: return lambda: i
...:
In [6]: callbacks = [make_callback(i) for i in range(10)]
In [7]: [c() for c in callbacks]
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [1]: callbacks = [lambda: i for i in range(10)]
In [2]: [c() for c in callbacks]The right answer is:
Out[2]: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
This is due to the fact that i is bound to the same variable in all the lambdas, and has the final value of 9.
There are two ways to overcome this. The first is to use the fact the default arguments are evaluated at function creation time (which is another known gotcha).
In [3]: callbacks = [lambda i=i: i for i in range(10)]
In [4]: [c() for c in callbacks]
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The second is to create a function generator function:
In [5]: def make_callback(i):
...: return lambda: i
...:
In [6]: callbacks = [make_callback(i) for i in range(10)]
In [7]: [c() for c in callbacks]
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Wednesday, March 14, 2012
Reading Avro Files Faster than Java
At work, we use a lot of Avro. One of the problems we faced was that the Python Avro package is very slow comparing to the Java one. The goal then was to write fastavro which is a subset of the avro package and should be at least as fast as Java. In this post I'll show how fastavro became faster than Java and also Python 3 compatible.
Going Fast
The Python avro package uses classes and properties heavily. This might allow for nice design but since function calls in Python are expensive it has a cost. The approach was to strip down most of the code in the avro package to one simple module, eliminating as many function calls as possible along the way and using only built in types. After some tweaking, fastavro was churning through the 10K records benchmark in about 2.6seconds (comparing to 13.9 seconds of the avro package). It was a nice speedup but the goal was to be as fast as Java (which was doing about 1.8sec).
Going Faster
Enter Cython. fastavro compiles the Python code without any specific Cython code. This way on machines that do not have a compiler users can still use fastavro. This complicated the build process a bit since now the C extension is generated using Cython in external Makefile. The code in fastavro first tries to import the C extension and if it fails imports the pure Python one.
This approach gave a 2x speedup (benchmark of 10K records done in 1.5seconds). Again, this is without any Cython specific code.
Python 3 Support
The initial Python 3 support was written on the first day of PyCon. However after hearing Robert Brewer's excellent talk I decided to take his advice and write a small compatibility layer (six was not used for various reasons).
As Robert said, this approach made fastavro better with strings, unicode and other things which were glossed over the 2.X only code. The build system was simplified a lot comparing to the one with the initial Python 3 support.
End Result
The end result is a package that reads Avro faster than Java and supports both Python 2 and Python 3. Using Cython and a little bit of work the was achieved without too much effort.
As usual, the code can be found on bitbucket.
Going Fast
The Python avro package uses classes and properties heavily. This might allow for nice design but since function calls in Python are expensive it has a cost. The approach was to strip down most of the code in the avro package to one simple module, eliminating as many function calls as possible along the way and using only built in types. After some tweaking, fastavro was churning through the 10K records benchmark in about 2.6seconds (comparing to 13.9 seconds of the avro package). It was a nice speedup but the goal was to be as fast as Java (which was doing about 1.8sec).
Going Faster
Enter Cython. fastavro compiles the Python code without any specific Cython code. This way on machines that do not have a compiler users can still use fastavro. This complicated the build process a bit since now the C extension is generated using Cython in external Makefile. The code in fastavro first tries to import the C extension and if it fails imports the pure Python one.
This approach gave a 2x speedup (benchmark of 10K records done in 1.5seconds). Again, this is without any Cython specific code.
Python 3 Support
The initial Python 3 support was written on the first day of PyCon. However after hearing Robert Brewer's excellent talk I decided to take his advice and write a small compatibility layer (six was not used for various reasons).
As Robert said, this approach made fastavro better with strings, unicode and other things which were glossed over the 2.X only code. The build system was simplified a lot comparing to the one with the initial Python 3 support.
End Result
The end result is a package that reads Avro faster than Java and supports both Python 2 and Python 3. Using Cython and a little bit of work the was achieved without too much effort.
As usual, the code can be found on bitbucket.
Thursday, February 23, 2012
Super Simple Mocking
There are many mocking libraries for Python out there. Due to the dynamic nature of Python I find them an overkill. Below is a super simple mocking library that works for me.
Note that for some types (such as C extensions, objects with __slots__ ...) this will not work since they do not have a __dict__.
EDIT: Following HackerNews comments , I've changed the interface to mock(obj, **kw).
Note that for some types (such as C extensions, objects with __slots__ ...) this will not work since they do not have a __dict__.
EDIT: Following HackerNews comments , I've changed the interface to mock(obj, **kw).
Sunday, February 05, 2012
Adding Key Navigation to Your Web Site
I don't like using the mouse and thankful for every web site that adds keyboard navigation (like Google Reader). Be nice to your users and add some yourself.
jQuery makes it super easy to add keyboard navigation to your site, below is a simple example adding keyboard navigation. "k/j" for up/down, "o" for opening an item and "?" for toggling help. JavaScript code starts at line 90.
jQuery makes it super easy to add keyboard navigation to your site, below is a simple example adding keyboard navigation. "k/j" for up/down, "o" for opening an item and "?" for toggling help. JavaScript code starts at line 90.

Wednesday, January 11, 2012
fastavro with Cython
Added an optional step of compiling fastavro with Cython. Just doing that, with no Cython specific code reduced the time of processing 10K records from 2.9sec to 1.7sec. Not bad for that little work.
Also added a __main__.py so you can use fastavro to process Avro files:
Also added a __main__.py so you can use fastavro to process Avro files:
- python -m fastavro weather.avro # Dump records in JSON format
- python -m fastavro --schema weather.avro # Dump schema

Friday, January 06, 2012
fastavro
Just released fastavro to PyPI. It has way less features than the official avro package, but according to my tests it's about 5 times faster.

Tuesday, December 27, 2011
How To Use A Chat To Amplify Your Team
A chat room is a great tool for any team. I've worked both in distributed and
"local" team and in both cases a central chat room was one of the most
effective tools we used. The chat room is the central location for updates,
conversations, shared knowledge and more. It's also highly effective in many open source projects.Starting is super easy, you can either set an internal server in your company with one of many open IRC/Jabber servers or try an external service (like Campfire, or HipChat).
The success of the chat room depends on the signal/noise ratio in the main room. Try to have every new conversation start in the main room, and only if it becomes to noisy move it to another room. 1/1 conversations are hiding information from the team and should be used only for personal communication.
Don't forget add services to the chat room. It's easy to add build notification, source commits, reminders and other smart bots. We use (Jenkins Jabber plugin) to get build notification. However be careful not to generate too much noise and tweak all these bots.
Logging and searching is another critical feature. Some services (like Campfire) provide it out of the box. If your chat server does not provide logging, it's pretty easy to add it with one of the many logging bots out there, and hooking search on top of the logs is pretty easy as well. (That's what we did with selenium.saucelabs.com which is a combination of Supybot and Omega).
Another issue is presence, people need to make it clear when they are "in" or "out" of the room. In some cases when the server logs it's as easy as login/logout. In other cases just notify the team your are away (we use the IRC /me lunching a lot). Stating that it's acceptable to be "out" of the room allows people to close the chat when they need to be in the zone.
So go ahead, set a chat for you team. Soon you'll wonder how you managed before.
Thursday, December 15, 2011
Decimals Class Decorator
A friend at work had a problem where he wanted to make sure some attributes are always Decimal.
We considered using the excellent traits library, but it's an overkill and we didn't want to introduce another dependency. For me this looked like a job for properties but we wanted some way to generate the properties automatically. Lucky for us we now have class decorators (in the old days I'd probably use a metaclass).
We considered using the excellent traits library, but it's an overkill and we didn't want to introduce another dependency. For me this looked like a job for properties but we wanted some way to generate the properties automatically. Lucky for us we now have class decorators (in the old days I'd probably use a metaclass).
Friday, December 02, 2011
branches
At work, our workflow involves JIRA and feature branches.
We name the feature branches in the name of the issue they are solving.
However when doing hg branches it's hard to know what branch you want.
Below is a small script that annotates the output of hg branches with the issue description from JIRA (and also added the branch parent).
However when doing hg branches it's hard to know what branch you want.
Below is a small script that annotates the output of hg branches with the issue description from JIRA (and also added the branch parent).
Friday, November 11, 2011
VirtualBox and USB
A little something I found out, writing it here in hope someone else will find it useful.
I'm on a Ubunbu system (11.10), and needed to connect to a USB device from an XP VM (wanted to sync and upgrade iPod touch, there is no iTunes for Linux). I couldn't connect the XP VM to any USB port (the USB menu was empty). The solution is to add yourself to the vboxusers group.
Open Users and Group, click on Manage Groups and double click on vboxusers and make sure your name is checked. After that logout and login, you should see the USB devices in the USB menu now.
I'm on a Ubunbu system (11.10), and needed to connect to a USB device from an XP VM (wanted to sync and upgrade iPod touch, there is no iTunes for Linux). I couldn't connect the XP VM to any USB port (the USB menu was empty). The solution is to add yourself to the vboxusers group.
Open Users and Group, click on Manage Groups and double click on vboxusers and make sure your name is checked. After that logout and login, you should see the USB devices in the USB menu now.
Tuesday, November 01, 2011
Summarize tuples
Raymond asked "Group the list of tuples on a given field and sum or count selected other fields.", here's my solution using sqlite3.
(original answer here).
Friday, October 28, 2011
Using dbus To Control Pidgin
I using Pidgin as my IM client, however after work I'd like to disconnect from our jabber server. Being the command like geek I am, I wrote the following. (Earlier version was written in bash using purple-remote
.)
You can learn more about Pidgin dbus interface here.
Saturday, October 15, 2011
Finding Module Version
A friend at work asked me how can he find which version of Python module is currently installed. The quick answer is to use pip:
pip freeze | grep <module>
pip freeze | grep <module>
Friday, September 30, 2011
Old Berlios Projects
Seems like Berlios is closing down. I've placed a backup of my old projects here. Let me know if you like to take ownership on one/several of them.
Using Generators in nose Tests
Sometimes you have many tests that do exactly the same thing but with different data. nose provides an easy way to do that with tests that return generators.
Subscribe to:
Posts (Atom)