reloading modules (was Re: [Zope3-dev] Re: Google SoC Project)

Shane Hathaway shane at hathawaymix.org
Fri May 12 15:30:32 EDT 2006


Jim Fulton wrote:
> I also think there is a real opportunity in allowing reload to fail.
> That is, it should be possible for reload to visibly fail so the user
> knows that they have to restart.  Then we only reload when we *know*
> we can make changes safely and fail otherwise.  For example, in the common
> case of updating a class, we can update the class in place.  If there
> aren't any other changes, then we know the reload is safe.

That's insightful.  Zope 2's refresh really should refuse to reload 
sometimes.  Right now it just trusts whoever wrote the "refresh.txt" file.

> Here's an idea: When we do a new-improved reload, we:
> 
> 1. Reevaluate the code in the pyc, getting the original dictionary.
> 
> 2. Recompile and evaluate the code without writing a new pyc.

Reloadable modules better not cause side effects at import time!

> 3. Compare the old and new dictionaries to find changes.  If we
>    don't know how to compare 2 items, we assume a change.  Note
>    removing a variable is considered an unsafe change.  Adding a
>    variable is assumed to be a safe change as long as a variable of
>    the same name hasn't been added to the module dynamically.
> 
> 4. We consider whether each of the changes is safe.  If any change
>    is unsafe, we raise and error, aborting the reload.  A change is
>    safe if the original and new variables are of the same type, the
>    values are mutable and if we know how to update the old value
>    based on the new value.  In addition, for a change to be safe,
>    the original value and the value currently in the module must be
>    the same and have the same value.  That is, it can't have been
>    changed dynamically.

It sounds like populating of any sort of registry in a module would 
prevent the module from being reloaded.  Take this for example:

# module "mimestuff.py"
content_types = {}
def add_content_type(name, extension):
     content_types[name] = extension

As soon as anyone calls add_content_type(), including the module itself, 
the state of the content_type dict changes from the original value. 
That's fine by me if that's what you intended.  Reloading modules 
containing registries never seemed like a good idea to me anyway.

> 5. We apply the changes and write a new pyc.

The server might not have write access to its code directory.  Maybe we 
can't reload if the server can't write the .pyc, since writing the .pyc 
is required to perform further reloads.

> This boils down to merging differences at the Python level.
> We fail if we don't know how to apply the diff. At that point,
> the user knows they need to restart to get the change.
> 
> Hm. This feels kind of workable.  It might even make a good PEP
> for a "safe reload".

It's certainly an improvement.  It's still possible for other modules to 
retain state based on a reloadable module's old state.  Should we worry 
about that?  Is it something that programmers understand intuitively 
enough that when they run into it, they won't be baffled?

Shane


More information about the Zope3-dev mailing list