Saturday, July 22, 2006

my beloved

You want to know why you should program in python ?
Check this: http://www.linuxjournal.com/article/3882

Quote from the author of fetchmail, a good old hacker:

"Of course, this brought me face to face once again with Python's pons asinorum, the significance of whitespace. This time, however, I charged ahead and roughed out some code for a handful of sample GUI elements. Oddly enough, Python's use of whitespace stopped feeling unnatural after about twenty minutes. I just indented code, pretty much as I would have done in a C program anyway, and it worked.

That was my first surprise. My second came a couple of hours into the project, when I noticed (allowing for pauses needed to look up new features in Programming Python) I was generating working code nearly as fast as I could type. When I realized this, I was quite startled. An important measure of effort in coding is the frequency with which you write something that doesn't actually match your mental representation of the problem, and have to backtrack on realizing that what you just typed won't actually tell the language to do what you're thinking. An important measure of good language design is how rapidly the percentage of missteps of this kind falls as you gain experience with the language.

When you're writing working code nearly as fast as you can type and your misstep rate is near zero, it generally means you've achieved mastery of the language. But that didn't make sense, because it was still day one and I was regularly pausing to look up new language and library features!

This was my first clue that, in Python, I was actually dealing with an exceptionally good design. Most languages have so much friction and awkwardness built into their design that you learn most of their feature set long before your misstep rate drops anywhere near zero. Python was the first general-purpose language I'd ever used that reversed this process."

python is really cool, coding simple readable stuff is so easy an fast. Here is something I coded in about 1 hour, which will probably give you the same kind of stuff valgrind would (on pure C programs who just link with libc).

[bsergean@flanders bin]$ cat purify.py
#!/usr/bin/env python

"""
Author: bsergean@adobe.com
Purpose: equivalent to valgrind --tool=memcheck but worse :)
History: boring friday morning
Bugs: ltrace doesn't trace calls from shared library linked with your lib.
"""

import sys
import os
import re

def purify(argv):
cmd = 'ltrace -e malloc,free,realloc ' + ' '.join(argv) + ' 2>&1'
pipe = os.popen(cmd, 'r')
mem = {}
total_allocated, total_alloc, total_free = 0, 0, 0

for line in pipe.readlines():
if line.startswith('malloc'):
total_alloc += 1
m_value, m_ptr = re.compile('malloc\((\d*)\)\s*=\s*(0x[0-9a-f]*)').findall(line)[0]
print '%d bytes malloced at @%s' % (int(m_value), m_ptr)
mem[m_ptr] = int(m_value)
total_allocated += int(m_value)

if line.startswith('realloc'):
total_alloc += 1
r_old_ptr, r_value, r_new_ptr = re.compile('realloc\((0x[0-9a-f]*|NULL), (\d*)\)\s*=\s*(0x[0-9a-f]*)').findall(line)[0]
print '%d bytes from @%s were realloced at @%s' % (int(r_value), r_old_ptr, r_new_ptr)
if r_new_ptr != r_old_ptr and r_old_ptr != 'NULL':
del mem[r_old_ptr]
mem[r_new_ptr] = int(r_value)
total_allocated += int(r_value)

if line.startswith('free'):
total_free += 1
f_ptr = re.compile('free\((0x[0-9a-f]*|NULL)\)').findall(line)[0]
print f_ptr, 'freed'
if f_ptr != 'NULL':
if mem.has_key(f_ptr):
del mem[f_ptr]
else:
print f_ptr, 'was never allocated before !!'

if not len(mem):
print 'No memory leak'
else:
print 'Memory leak !!'
print sum(mem.values()), 'bytes leaked in', len(mem), 'blocks'

print total_alloc, 'allocs,', total_free, 'frees,', total_allocated, 'bytes allocated.'

if __name__ == "__main__":
purify(sys.argv[1:])
[bsergean@flanders bin]$