NameError in cross imports of modules

Thomas Wouters thomas at xs4all.net
Sun Feb 4 10:54:37 EST 2001


On Sun, Feb 04, 2001 at 07:39:21AM +0000, Jay O'Connor wrote:
> Thomas Wouters wrote:

> > and as far as I'm concerned there are only two viable uses: the way
> > os.py uses it (import any and all symbols from a platform-dependant C
> > module) and the way Mailman uses it (import all symbols from a template
> > config file into the user-editable config file, so it only needs to contain
> > overriding values.) I still owe Fred a "From module import * considered
> > harmful" tutorial-section ;-P If prefixing all module variables with the
> > module name is too painful because the module name is too long or unclear,
> > consider using 'import my_long_module as _a' or some such.

> I've followed the convention (maybe I made it up for myself :)  That if
> I'm importing classes, I use "from package import *" such as "from gtk
> import *", but if I'm importing a module of functions, I just use
> "import package name" such as "import string" and use the module name
> prefix for all function calles.

> Don't know if it's good or not...

Well, I already made clear here that the answer is 'no' :-) I'm not sure
what kind of situation you are in when you say you are 'importing classes'
(I've never done that, myself, and it's only possible since Python 2.1 in
any case :), but 'from module import *' imports a lot more than classes, and
can do all kinds of nasty things, like shadowing builtins and globals, and
clobbering your own variables. If you want to import a couple of class names
from a module to your own namespace, you best name them explicitly, so you
are sure those are the only names imported. And more importantly, so that
you, and everyone else, can always find out where a name comes from. For
instance:

from spamsong import *

<X lines of code>

from Eric import *

<several hundred lines of code>

class ExtendedViking(Viking):
    <lots of code relying on what Viking is>

Where did the 'Viking' come from ? Everyone knows both the spamsong and Eric
the Viking feature Vikings. Maybe spamsong named its viking differently when
you first wrote the module, or you never noticed spamsong had a viking
because it was always overwritten by the one in Eric. Or maybe it's the
other way 'round, you intended to use spamsong's Viking, but didn't know
Eric had one, too. Or maybe Eric grew its viking later. Or even worse, both
spamsong and Eric had vikings, but the on in Eric wasn't supposed to be
exported (like, it should have been named _Viking and someone forgot) and
they removed it in a later release -- but you were relying on that
undocumented misfeature. Suddenly your extended viking behaves differently,
'for no apparent reason'.

Now if you had written 
 
from spamsong import Viking
from Eric import Viking

It would have been obvious from the start that you were overwriting the
first with the second. You wouldn't have run into all those ambiguities
because if either Viking hadn't existed when you first wrote it, you would
have seen the import errors. And if either Viking disappeared in a later
release, this would also cause a nice clean error.

The only real, justifiable (in my eyes) use for 'from ... import *' is when
you have two modules, and you want one to act as a 'front' for the other.
This is what os.py does: it grabs a platform-dependant module and all the
names it defines. (posix on POSIXish systems, nt on windont, mac on
macintoshes, etc. And more can be added without breaking or confusing code.)
os.py and the platform-specifc module are not meant to be used seperately,
and not meant to be of different versions, either. 

The same goes for the Mailman mm_cfg.py and Defaults.py. mm_cfg.py is a
config file (in handy Python format) that is created if it doesn't exist,
but is never overwritten by vesion updates. Instead, Defaults.py is
provided, which contains default values for all configuration directives.
This file should not be edited, because it *is* overwritten by Mailman
version updates. mm_cfg.py does not provide any functionality itself, and
the user is supposed to be able to override values from Defaults.py. The
user should not invent new values or add new code to mm_cfg.py, because that
might mask new configuration directives in future versions, causing strange
breakage. It's purely a 'override the defaults' opportunity.

These two uses are so specific, and the techniques so infrequently used, I
really wish there *was* no 'from-import *'. The above could have been done
in a more elaborate, verbose and less abusable way :-) I doubt 'from-import
*' will be removed even in Py3K, but I can still wish, can't I ? :-)

-- 
Thomas Wouters <thomas at xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!




More information about the Python-list mailing list