pko.ch

Reflections about reflection

Archive for the ‘python’ Category

Taming KbdMgr.exe

Saturday, March 28th, 2009

I have a bootcamp’ed Macbook Pro. As many people, I experienced some lagging sound and graphics from the computer, apparently at random. I googled it a bit, and found DPCs were the cause of it. And the cause DPCs were so slow were some drivers and KbdMgr.exe, a small app that listens to the hardware keys to raise brightness and stuff.

I updated the drivers, and the lag dropped a bit, but not that much. Then I turned to KbdMgr.exe. I read that a quick fix was to set the affinity to the second core and set it to minimum priority. And so I did, and it worked! However, It was just a pain in the butt to do that dance on each boot. I thought of doing some wrapper exe for KbdMgr.exe, but just the thought of downloading Visual Studio and all the SDKs gave me nauseas. And python popped into my mind.

After some 15 minutes of research, I found win32all. And from there, It was just remembering all of the win32 I had forgotten. I eventually churned out some code to scratch my itch.

import win32api
import win32com.client
import win32process
import win32con
import time
import sys, traceback

class ProcessSeekerThrottler(object):

    def __init__(self):
        self.coup_de_grace = self.throttle_and_set_affinity
        self.backoff_interval = 1.0

    def throttle_and_set_affinity(self,pid):
        proc = win32api.OpenProcess(win32con.PROCESS_SET_INFORMATION, 0, pid)

        win32process.SetProcessAffinityMask(proc,0x02)
        win32process.SetPriorityClass(proc,win32process.IDLE_PRIORITY_CLASS)

        win32api.CloseHandle(proc)

    def pids_for(self,process_name):
        self.WMI = win32com.client.GetObject('winmgmts:')
        results = self.WMI.ExecQuery('select * from Win32_Process where Name="%s"'%(process_name,))
        if len(results) < 1:
            raise Exception("Not found: %s"%(process_name,))
        else:
            return [result.Properties_('ProcessId').Value for result in results]

    def hunt_pid_for(self,process_name):
        done = False
        while not done:
            try:
                [self.coup_de_grace(pid) for pid in self.pids_for(process_name)]
                print "Killed!"
                done = True
            except Exception as e:
                print >> sys.stderr, "-"*60
                traceback.print_exc(None,sys.stderr)
                print >> sys.stderr, "Backing off."
                time.sleep(self.backoff_interval)

if __name__ == '__main__':
    try:
        ProcessSeekerThrottler().hunt_pid_for("KbdMgr.exe")
    except Exception as e:
        traceback.print_exc(None,sys.stderr)
        raw_input()

There’s no silver bullet, but there’s a silver DSCM. And it’s quick.

Saturday, August 23rd, 2008

Pre scriptum: This was dangling in my drafts forever. I just decided to post it as it is.

In this post: Why I use Mercurial (sometimes abbreviated as hg) but not Git, and why I like it.

One day, some moons ago, I watched a presentation with Linus on Git, and how it would forever change our life. He explained why it’s a must-use on a very big distributed team or/and at a personal level. I mostly agreed. I still thought this was just a clever hack to solve merge conflits on svn and keep changes controlled on a mental level. CVS is dead, SVN is not. For most small teams, SVN is just a shortcut for the common workflow one would do with git, except for one little thing: you commit locally, and publish as needed.

Mercurial, or any DSCM, is great for detaching the act of committing work (accepting it as a valid step towards a goal) from the act of publishing work (putting your modifications up for other parties).

I prefer Mercurial over Git for the polish and supporting the anti-”linus is god” movement. I really didn’t like the way I was told he dismissed the idea of using incremental logs. I’m not being an extremist, or i would use Codeville.

Memoization in Python: easier than what it should be

Friday, August 22nd, 2008

I was writing some DB-access-intensive Python application and felt the need to cache function results. After fiddling with some dictionaries, I felt there was some underlying pattern I wasn’t spotting. Then it hit me. I was just memoizing function calls.

So I came up with this decorator.

import functools
import cPickle
def memoize(fctn):
        memory = {}
        @functools.wraps(fctn)
        def memo(*args,**kwargs):
                haxh = cPickle.dumps((args, sorted(kwargs.iteritems())))

                if haxh not in memory:
                        memory[haxh] = fctn(*args,**kwargs)

                return memory[haxh]
        if memo.__doc__:
            memo.__doc__ = "\n".join([memo.__doc__,"This function is memoized."])
        return memo

Python is really easy to write.

23 August 2008 – Update: Corrected the bug pointed out by John.
25 August 2008 – Update: Improved as per reddit comments‘s suggestions.

Moar python on Bluehost

Thursday, May 8th, 2008

It all began with me wanting Mergurial (hg for short) on Bluehost. I find mercurial as good as git but with more polish. I just followed some tutorial to get hg on Bluehost, and it was good.

However, I longed for more. Pylons more. It’s a lot of packages to install, so I really didn’t want to do it by hand. If I resign to do it this time, it will happen on my next coding whim too. I tried to use ez_setup, but it would screw up with my prefix. Tried virtual python from the easy_install guys, no go either. Tried messing with PYTHONPATH, PATH and the like, but it became really ugly really fast.

Bluehost’s python is very old. Has a big beard and all. Bluehost already forces me to use cgi after all, so i get to choose who runs the script. It might as well be my own version of python. And so it was! Grabbed the source, built it with a prefix and, lo and behold, I had a shiny python working. That simple. The night before it was configuration madness. This time, ./configure --PREFIX=$HOME/local && make && make install or some cash equivalent operation. All went good from there.

Lesson learned: In shared hosting, when forced to use cgi, ./configure --PREFIX=$HOME/local goes a long way. Use it!