[mod_python] Module reload/derived class problem

Alan Davies alan at goatpunch.com
Fri Mar 4 13:42:09 EST 2005


Hi,

I just wanted to contribute some information about a problem I'd been
having, for a while that I couldn't find a clear answer to anywhere.
It's a combination of two problems that I'd seen discussed in different
places.

The problem was this:

    I created a class 'A', in it's own module, that serves up a dynamic
    site.

    I then derived a class 'B' from 'A', that adds a few extras. Some of
    'A's methods were overridden, deferring functionality to the base
    class by explicitly calling 'A' (e.g. calling A.foo(self) from
    within
    B::foo()).

    Everything seemed to work as expected, but once in a while I would
    get an error like this when a method on 'B' was called:

        TypeError: unbound method foo() must be called with A instance 
                   as first argument (got B instance instead)

    The error would go away when I restarted Apache.

The problem was, of course, caused by the module containing 'A' being
reloaded. The reloads would happen when I made a change to 'A', which is
called directly by mod python. Module 'A' would reload when I modified
it, which I would do occasionally, without thinking to test 'B' which
shouldn't have been impacted by the changes.

The reloaded class 'A' is a different class from the original 'A'. I
suppose this has to happen when a module is reloaded, and it's probably
a feature that just looks like a bug.

The problem can be demonstrated without even using mod_python, by the
following simple example:

------ file testa.py ---------

class A:
    def foo(self):
        print "A:foo"

-----file testderive.py -----

import testa

class B(testa.A):
    def foo(self):
        print "B::foo"
        testa.A.foo(self)

b = B()

print "first request:"
b.foo()

# simulate mod_python performing a reload
reload(testa)

print "second request:"
b.foo()

---- testderive.py output ---------

>>> 
first request:
B::foo
A:foo
second request:
B::foo
Traceback (most recent call last):
  File "testderive.py", line 16, in ?
    b.foo()
  File "testderive.py", line 6, in foo
    testa.A.foo(self)
TypeError: unbound method foo() must be called with A instance as first
argument (got B instance instead)

------------------------------------

Now that I've realised why I get that error message, I can avoid the
problem by brute force either by 'touch'ing 'B' every time I change
'A', or by restarting Apache after a change to 'A' (instead of a week
later when I notice the problem).

More advanced ideas for fixing the module reloading problem would be
appreciated.

Hope someone finds this useful,

--Alan


More information about the Mod_python mailing list