[mod_python] Udate python modules without restarting Apache

Graham Dumpleton grahamd at dscpl.com.au
Thu Oct 14 17:21:52 EDT 2004


On Oct 14 14:51, "Nicolas Lehuen" <nicolas at lehuen.com> wrote:
>
> Subject: RE: [mod_python] Udate python modules without restarting Apache
>
> This __clone__() method is a very neat idea indeed ! For the moment I prefer
> not to keep any data between reloads (what needs to be kept is in the
> database), but there may be occurrences where such a mechanisms would be
> handy.

The actual data may be in the database, but if one is using a database
connection pooling object, one has to keep that somewhere. That is one
candidate for types of objects that you may want to preserve across a
reload and not simply throw away.

> Right now I'm trying to use imp.new_module but I get curious results...
> Apparently some classes that are imported from other modules are redefined
> even though they should not. The net result is that some isinstance() tests
> fail where they should not (reminds me of ClassLoader problems in Java). I
> tried to build a simple test case exhibiting the problem, but it does not.
> What's for sure, is that when I do :
> 
> exec source in module.__dict__
> 
> If module is a fake module object (a place holder class Module(object):
> pass), all my code is OK. If it is a real module, I get weird behaviours.
> I'm still investigating on the subject.

Reloading of modules can always be a problem when one is comparing the
type of objects as you have to be careful that something hasn't stashed away
a copy of an older class object for type comparison, or conversly is using a
newer version of the class object to check the type of an object created from
the older instance.

This was one of the issues that originally came up in prior email, specifically
the Servlet class from mpservlets. In that case it was because a module was
being imported using "import" in one place and "apache.import_module()"
in another. As such there were two actual instances of the Servlet class and
comparing the type of an instance based on one against the other class type
was going to fail.

The problem can still arise even when one consistently uses a module
import and caching mechanism, as such mechanisms typically only look at
the highest level import and not any sub imports that may have been done
by the object. Thus, you can have stale copies of modules still in memory
until the appropriate parent module is also reloaded, flushing out the stale
sub module.

BTW, the __clone__() method could also be conceivably used to copy across
classes as opposed to instances of classes. You might therefore have something
like:

  def __clone__(module):
    module.Interface = Interface

  if not globals().has_key("Interface"):
    class Interface:
      def method(self,object):  pass

  class Implementation(Interface):
    def method(self,object):
      if isinstance(object,Interface):
        ...

That is, have a simple class definition which defines the interface, much like
interface objects in Java. Have the actual implementation derive from that.
In code create instances of the Implementation, but when doing isinstance()
checks, compare it to the Interface base class.

Thus, the Interface class definition is always the same actual class type object
because it is preserved across reloads. Although the derived class may be
called Implementation in every version of the module, it is actually a different
class type object in memory. To compare types of Implementation objects is
not going to work if instances are based on different versions, but if your
check is for them being a derived instance of Interface, you woud be okay.

Although for a robust system that can easily be updated if necessary without
restarting Apache you could go to this extent, I frankly doubt many, if any at
all would bother to do so.

I will be interested to here what is causing your problem in case there is
something I have missed about how this stuff operates.


--
Graham Dumpleton (grahamd at dscpl.com.au)


More information about the Mod_python mailing list