Deprecating reload() ???

David MacQuigg dmq at gain.com
Tue Mar 16 13:58:23 EST 2004


On Tue, 16 Mar 2004 08:58:38 -0600, Skip Montanaro <skip at pobox.com>
wrote:
[snip]
>It seems to me that you have a continuum from "don't update anything" to
>"track and update everything":
>
>    don't update       update global       update all direct      update
>      anything         funcs/classes           references       everything
>
>      reload()         super_reload()            Dave            nobody?
>
>Other ideas have been mentioned, like fiddling the __bases__ of existing
>instances or updating active local variables.  I'm not sure precisely where
>those concepts fall on the continuum.  Certainly to the right of
>super_reload() though.
>
>In my opinion you do what's easy as a first step then extend it as you can.
>I think you have to punt on shared objects (ints, None, etc).  This isn't
>worth changing the semantics of the language even in some sort of
>interactive debug mode.

I agree, punt is the right play for now, but I want to make one
clarification, in case we need to re-open this question.  The semantic
change we are talking about applies only to the 'is' operator, and
only to a few immutable objects which are created via a reload of a
module in "debug" mode.  All other objects, including those from other
modules remain unchanged.  Objects like None, 1, 'abc', which are
treated as shared objects in normal modules, will be given a unique ID
when loaded from a module in debug mode.  This means you will have to
use '==' to test equality of those objects, not 'is'.  Since 'is' is
already a tricky, implementation-dependent operator that is best
avoided in these situations, the impact of this added option seems far
less than "changing the semantics of the language".

I'll hold off on any push for expanding super_reload until I have a
good use case.  Meanwhile, I'll assume I can work with the existing
reload.  This will probably involve a combination of programming
discipline and user education.  In programming, I'll do what I can to
avoid problems with the modules I expect will be reloaded.  Where
"direct" references are made to constants or other objects in a
reloaded module, I'll be sure to refresh those references at the
beginning of each code section.  In my user manual, there will
probably be statements like:  """Don't attempt to reload the stats
module while a simulator is active.  The reload function can save
having to restart your entire session, but it does not update
functions or data that have already been sent to the simulator.  As
with reloading statefiles, always kill and restart the simulator after
a reload of the stats module."""

>Sitting for long periods in an interactive session and expecting it to track
>your changes is foreign to me.  I will admit to doing stuff like this for
>short sessions:
>
>    >>> import foo
>    >>> x = foo.Foo(...)
>    >>> x.do_it()
>    ...
>    TypeError ...
>    >>> # damn! tweak foo.Foo class in emacs
>    >>> reload(foo)
>    >>> x = foo.Foo(...)
>    >>> x.do_it()
>    ...
>
>but that's relatively rare, doesn't go on for many cycles, and is only made
>tolerable by the presence of readline/command retrieval/copy-n-paste in the
>interactive environment.
>
>Maybe it's just the nature of your users and their background, but an
>(edit/test/run)+ cycle seems much more common in the Python community than a
>run/(edit/reload)+ cycle.  Note the missing "test" from the second cycle and
>from the above pseudo-transcript.  I think some Python programmers would
>take the opportunity to add an extra test case to their code in the first
>cycle, where in the second cycle the testing is going on at the interactive
>prompt where it can get lost.  "I don't need to write a test case.  It will
>just slow me down.  The interactive session will tell me when I've got it
>right."  Of course, once the interactive sessions has ended, the sequence of
>statements you executed is not automatically saved.  You still need to pop
>back to your editor to take care of that.  It's a small matter of
>discipline, but then so is not creating aliases in the first place.

This is a good description of the program development cycle.  My users
(circuit design engineers) won't be doing program development, but
will be making changes in existing data and functions.  My goal is to
make that as easy as possible. The biggest step is offering Python as
the scripting language, rather than SKILL, OCEAN, MDL, or a number of
other CPL's ( complex proprietary languages ).  I expect them to learn
in two days enough Python to understand a function definition, and to
be able to edit that definition, making it do whatever they want.

>    Dave> Reload() will always be a function that needs to be used
>    Dave> cautiously.  Changes in a running program can propagate in strange
>    Dave> ways.  "Train wreck" was the term another poster used.
>
>Precisely.  You may wind up making reload() easier to explain in the common
>case, but introduce subtleties which are tougher to predict (instances whose
>__bases__ change or don't change depending how far along the above continuum
>you take things).  I think changing the definitions of functions and classes
>will be the much more likely result of edits requiring reloads than tweaking
>small integers or strings.  Forcing people to recreate instances is
>generally not that big of a deal.
>
>Finally, I will drag the last line out of Tim's "The Zen of Python":
>
>    Namespaces are one honking great idea -- let's do more of those!
>
>By making it easier for your users to get away with aliases like
>
>    x = M1.x
>
>you erode the namespace concept ever so slightly just to save typing a
>couple extra characters or executing a couple extra bytecodes.  Why can't
>they just type M1.x again?  I don't think the savings is really worth it in
>the long run.

    def h23(freq):
        s = complex(2*pi*freq)
        h0 = PZfuncs.h0
        z1 = PZfuncs.z1; z2 = PZfuncs.z2
        p1 = PZfuncs.p1; p2 = PZfuncs.p2; p3 = PZfuncs.p3
        return h0*(s-z1)*(s-z2)/((s-p1)*(s-p2)*(s-p3))

Notice the clarity in that last formula.  This is a standard form of a
pole-zero transfer function that will be instantly recognized by a
circuit design engineer.  The issue isn't the typing of extra
characters, but the compactness of expressions.

In this case we avoid the problem of local variables out-of-sync with
a reloaded module by refreshing those variables with every call to the
function.  In other cases, this may add too much overhead to the
computation.

-- Dave




More information about the Python-list mailing list