I see your 473 non-whitespace characters, and raise you 331.
[Edit:] Got it to 314 non-whitespace characters. Still has the flaw @slicer mentions below. =(...
By the powers vested in me by Python, I see your 314 and raise you 274.
I don't know Python, but following from what SiCrane said, could you perhaps make line 6 stick an 's' into the string a, removing the need for a substantially-identical string b?
EDIT: This seems to work with fewer characters, and I'm sure someone who has actually used Python, you know, ever, could do this in a smarter way.
a = 'bottles of beer'
w = 'on the wall.\n'
def D(i):
return i if i!=0 else 'no more'
def Q(i):
return a if i!=1 else "".join(a.split("s"))
def C(i):
return '\nTake one down and pass it around,' if i>0 else '\nGo to the store and buy some more,'
for i in range(99,-1,-1):
print D(i), Q(i), 'on the wall,', D(i), Q(i)+'.', C(i), D(i-1), Q(i-1), w
#print 'No more', b, 'on the wall, no more', b+'.'+C(i), '99', b, w
EDIT: Oops, I must have stolen swiftcoder's code to make that change at a moment when it was broken, so there's an off-by-one error in mine.