Mailing List Archive

Maintainability (was Re: Stackless & String-processing)
In article <001101bed3f2$5e8874a0$642d2399@tim>,
Tim Peters <tim_one@email.msn.com> wrote:
>
>That's fine for a one-man show. "Maintainability" in my life cuts across
>programmers, and it's Not Good for each person to reinvent their own basic
>machinery -- even to have the ability to do so. One reason I like Python is
>that it *doesn't* let the jerk down the hall invent their own control
>structures <0.5 wink>.

Yup. Today I had to lay down the law to our programming team: use of
the construct "from foo import *" is now expressly, explicitly, and
completely forbidden. "from foo import bar" is deprecated; "from foo
import foo" is acceptable; and "import foo" is strongly preferred.

I'd be in favor of getting "from foo import *" entirely out of the
language, but I suspect it's just too convenient for short hacks.
--
--- Aahz (@netcom.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6 (if you want to know, do some research)
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
>>>>> "Aahz" == Aahz Maruch <aahz@netcom.com> writes:

Aahz> Tim Peters <tim_one@email.msn.com> wrote:

>> That's fine for a one-man show. "Maintainability" in my life cuts
>> across programmers, and it's Not Good for each person to reinvent
>> their own basic machinery -- even to have the ability to do so. One
>> reason I like Python is that it *doesn't* let the jerk down the hall
>> invent their own control structures <0.5 wink>.

Aahz> Yup. Today I had to lay down the law to our programming team: use of
Aahz> the construct "from foo import *" is now expressly, explicitly, and
Aahz> completely forbidden. "from foo import bar" is deprecated; "from foo
Aahz> import foo" is acceptable; and "import foo" is strongly preferred.

Aahz> I'd be in favor of getting "from foo import *" entirely out of the
Aahz> language, but I suspect it's just too convenient for short hacks.

What Tim said about programmers not inventing control structures is somewhat
different than what Aahz put his foot down about. There's nothing wrong
with "from foo import *" when it's used in the right context. Some modules
in the standard distribution were designed specifically to support this
(types and Tkinter come to mind). Used willy-nilly, you can get into
trouble with it, one-man show or not.

Skip Montanaro | http://www.mojam.com/
skip@mojam.com | http://www.musi-cal.com/~skip/
847-475-3758
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
In article <14230.42741.34295.650213@153.chicago-05-10rs.il.dial-access.att.net>,
Skip Montanaro <skip@mojam.com> wrote:
>>>>>> "Aahz" == Aahz Maruch <aahz@netcom.com> writes:
>
> Aahz> Yup. Today I had to lay down the law to our programming team: use of
> Aahz> the construct "from foo import *" is now expressly, explicitly, and
> Aahz> completely forbidden. "from foo import bar" is deprecated; "from foo
> Aahz> import foo" is acceptable; and "import foo" is strongly preferred.
>
> Aahz> I'd be in favor of getting "from foo import *" entirely out of the
> Aahz> language, but I suspect it's just too convenient for short hacks.
>
>What Tim said about programmers not inventing control structures is somewhat
>different than what Aahz put his foot down about. There's nothing wrong
>with "from foo import *" when it's used in the right context. Some modules
>in the standard distribution were designed specifically to support this
>(types and Tkinter come to mind). Used willy-nilly, you can get into
>trouble with it, one-man show or not.

I'm afraid I can't agree that there's *ever* a good time to use "from
foo import *" in a multi-programmer environment. Too often, you have a
programmer new to a particular chunk of code trying to debug it; not
knowing exactly where a method/function call is coming from vastly
increases debugging time (particularly when there are hundreds of
modules and scripts). If you want to use an unadorned class/function,
you can just take the trouble to explicitly list it as "from foo import
bar, baz".

My point was related to Tim's in that we're both talking about how
Python's strait-jacket approach is a Good Thing; I'm simply using an
example where I think Python could actually be tightened.
--
--- Aahz (@netcom.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6 (if you want to know, do some research)
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Hi All--

Aahz Maruch wrote:
>
>
> I'm afraid I can't agree that there's *ever* a good time to use "from
> foo import *" in a multi-programmer environment. Too often, you have a
> programmer new to a particular chunk of code trying to debug it; not
> knowing exactly where a method/function call is coming from vastly
> increases debugging time (particularly when there are hundreds of
> modules and scripts). If you want to use an unadorned class/function,
> you can just take the trouble to explicitly list it as "from foo import
> bar, baz".
>

All true, except for perhaps Tkinter. And my soon-to-be-released
mayalib-1.2. Both are specifically designed to use 'from xxx import *'
and both carefully refrain from polluting your namespace. But possibly
you don't use Tkinter in your projects, Aahz? (I think I can safely
assume you don't use any Mayan dates. ...;-)

> My point was related to Tim's in that we're both talking about how
> Python's strait-jacket approach is a Good Thing; I'm simply using an
> example where I think Python could actually be tightened.
>

I think it's exactly as tight as it needs to be. If it were tighter,
people would spend more time and energy finding ways around the
restrictions, and it wouldn't be so attractive--and fun.

<houdini-died-in-a-straight-jacket>-ly y'rs,
Ivan
----------------------------------------------
Ivan Van Laningham
Callware Technologies, Inc.
ivanlan@callware.com
ivanlan@home.com
http://www.pauahtun.org
See also:
http://www.foretec.com/python/workshops/1998-11/proceedings.html
Army Signal Corps: Cu Chi, Class of '70
----------------------------------------------
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Skip Montanaro <skip@mojam.com> wrote:
|
| What Tim said about programmers not inventing control structures is somewhat
| different than what Aahz put his foot down about. There's nothing wrong
| with "from foo import *" when it's used in the right context. Some modules
| in the standard distribution were designed specifically to support this
| (types and Tkinter come to mind). Used willy-nilly, you can get into
| trouble with it, one-man show or not.
|

Here's a gotcha with import *:

import re
from string import * # Great whenever you're doing string processing
re.compile('abc')




:-(

I think the system modules should define all internal variables with a
'_' prefix! :-)

- Amit
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Skip Montanaro wrote:
>
> Some modules
> in the standard distribution were designed specifically to support this
> (types and Tkinter come to mind).

In the case of Types, it could easily have been designed
differently. Writing Types.List would not be much harder than
typing Listtype and would be easier to read as well.

As for Tkinter, I've gotten into the habit of always
writing Tkinter.Button, etc. and I think the qualification
is a good idea. It means, for example, I can have a
module called Fancy which implements a custom button
subclass and call it Fancy.Button. I like that better
than having to call the class Fancybutton or something.

So I wouldn't mind much if the * form of import
went away, either. You can easily write a function
which does the same thing if you really, really want it.

Greg
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Amit> import re
Amit> from string import * # Great whenever you're doing string processing
Amit> re.compile('abc')

Two points. One, the string module wasn't designed to be imported using
"from string import *". In my previous message I mentioned the types and
Tkinter modules. I'm not aware of any others that were explicitly designed
for that. Two, the bug that placed an object called "re" in the string
module at module scope was fixed several months ago.

% python
Python 1.5.2+ (#28, Jun 17 1999, 15:24:35) [GCC 2.7.2.3] on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import string
>>> dir(string)
[.'_StringType', '__builtins__', '__doc__', '__file__', '__name__',
'_apply', '_float', '_idmap', '_idmapL', '_int', '_long', 'atof',
'atof_error', 'atoi', 'atoi_error', 'atol', 'atol_error', 'capitalize',
'capwords', 'center', 'count', 'digits', 'endswith', 'expandtabs',
'find', 'hexdigits', 'index', 'index_error', 'join', 'joinfields',
'letters', 'ljust', 'lower', 'lowercase', 'lstrip', 'maketrans',
'octdigits', 'replace', 'rfind', 'rindex', 'rjust', 'rstrip', 'split',
'splitfields', 'startswith', 'strip', 'swapcase', 'translate', 'upper',
'uppercase', 'whitespace', 'zfill']

Look, Ma! No re!

Amit> I think the system modules should define all internal variables
Amit> with a '_' prefix! :-)

Again, the string.re thing was a bug. Most system modules do follow this
convention.

Skip Montanaro | http://www.mojam.com/
skip@mojam.com | http://www.musi-cal.com/~skip/
847-475-3758
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
In article <37974758.FF2DAE55@callware.com>,
Ivan Van Laningham <ivanlan@callware.com> wrote:
>Aahz Maruch wrote:
>>
>> I'm afraid I can't agree that there's *ever* a good time to use "from
>> foo import *" in a multi-programmer environment. Too often, you have a
>> programmer new to a particular chunk of code trying to debug it; not
>> knowing exactly where a method/function call is coming from vastly
>> increases debugging time (particularly when there are hundreds of
>> modules and scripts). If you want to use an unadorned class/function,
>> you can just take the trouble to explicitly list it as "from foo import
>> bar, baz".
>
>All true, except for perhaps Tkinter. And my soon-to-be-released
>mayalib-1.2. Both are specifically designed to use 'from xxx import *'
>and both carefully refrain from polluting your namespace. But possibly
>you don't use Tkinter in your projects, Aahz? (I think I can safely
>assume you don't use any Mayan dates. ...;-)

The point is that a programmer looking at a traceback has no way of
knowing from looking at a line of code in isolation where the
function/class comes from. At least with "from foo import bar" a search
through the source will discover which module/package bar comes from.

Although polluting the namespace is an issue (and as Greg points out, if
someone subclasses, you definitely do have a greater likelihood for
namespace collisions), I'm trying to hammer on the idea that specifying
where things come from is a critical issue.
--
--- Aahz (@netcom.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6 (if you want to know, do some research)
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
[.Aahz Maruch, hijacks a thread & holds it hostage to "import *"]

[.Skip Montanaro, regurgitates the company line -- as if that ever stopped a
terrorist]
> ...
> There's nothing wrong with "from foo import *" when it's used in
> the right context. Some modules in the standard distribution were
> designed specifically to support this (types and Tkinter come to mind).

[Aahz counterstrikes]
> I'm afraid I can't agree that there's *ever* a good time to use "from
> foo import *" in a multi-programmer environment. [followed by the usual
> good reasons]

Political power flows from the barrel of a gun; a language flowers on the
rotting corpse of its creator. Come the revolution, use of "from foo import
*" will be punishable by exile to Perland! For that matter, so will use of
the wretched "foo" <wink>.

It's still a valuable feature of the language, though, and the Official
History here is a tad revisionist. This business about modules being
designed specifically for use with * is a latter-day invention that popped
up around the time Tkinter.py appeared; in the beginning, "import *" served
its One True Purpose: to save a pile of tedious typing in interactive mode!
Try crunching some numbers interactively with and without "from math import
*", and the intended use of this construct shines.

The other <ahem> One True Purpose was to save a pile of tedious typing when
whipping up a throwaway prototype as quickly as possible.

Their may have been another, but all Sole True "*" Purposes are
characterized by ephemerality and solitude. Anyone using "import *" in
public, or over extended periods of time, may as well just admit that they
didn't even bother to ask the name of the last cheap hooker they paid for a
5-minute fling.

explicit-import-is-the-condom-of-responsible-programming-ly y'rs - tim
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Skip Montanaro wrote:

> Two points. One, the string module wasn't designed to be imported
> using "from string import *". In my previous message I mentioned
> the types and Tkinter modules. I'm not aware of any others that
> were explicitly designed for that.

You can add threading to your list.

someones-got-a-fondness-for-'t'-ly y'rs

- Gordon
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Skip Montanaro wrote:
> Some modules
> in the standard distribution were designed specifically to support this
> (types and Tkinter come to mind).

Greg Ewing writes:
> In the case of Types, it could easily have been designed
> differently. Writing Types.List would not be much harder than
> typing Listtype and would be easier to read as well.

I actually like the longer names on this one, but otherwise...

> As for Tkinter, I've gotten into the habit of always
> writing Tkinter.Button, etc. and I think the qualification

Though I think some of my co-workers disagree, I agree with you on
this one. Tkinter is a *terrible* module for the "import *" style.
James Henstridge's "gtk" module is much better about this, but enough
of the constants have short enough names that I won't use "import *".
Another problem of "import *" is that it makes introspection of a
module (using dir(), idle, whatever) more painful.

> So I wouldn't mind much if the * form of import
> went away, either. You can easily write a function
> which does the same thing if you really, really want it.

Yes.
Something that I'd like to see, that I don't think has been
mentioned for a long time, is some sort of "import ... as" statement.
I like qualifying the names from a module, but if I'm using them a lot
I want to give the module a short name. For instance,

import Tkinter as Tk

would be more comfortable, and is much more clear than:

import Tkinter
_tk = Tkinter
del Tkinter

Variants could include:

import package.module as pkgmod # pkgmod is the actual
# module, not the package

from package import module as pkgmod
# the same, possibly cleaner

from module import function as func

As I said, I haven't noticed this come up for a while, so maybe I'm
the only one, but I think this would encourage clarity and
"localizing" the names of imported modules (adding a leading _ so when
others "import *" from our modules their namespace isn't polluted too
much).


-Fred

--
Fred L. Drake, Jr. <fdrake@acm.org>
Corporation for National Research Initiatives
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Amit Patel writes:
> Here's a gotcha with import *:
>
> import re
> from string import * # Great whenever you're doing string processing
> re.compile('abc')

Amit,
This specific problem isn't present in the version in the CVS
repository; was it still a problem with the 1.5.2 release? Looking
through string.py, I didn't see any other problems of unintentionally
exported symbols.


-Fred

--
Fred L. Drake, Jr. <fdrake@acm.org>
Corporation for National Research Initiatives
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Skip Montanaro writes:
> Again, the string.re thing was a bug. Most system modules do follow this
> convention.

Many older ones do not, unfortunately.


-Fred

--
Fred L. Drake, Jr. <fdrake@acm.org>
Corporation for National Research Initiatives
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Hi All--

"Fred L. Drake" wrote:
>

[bobbitt]

> Yes.
> Something that I'd like to see, that I don't think has been
> mentioned for a long time, is some sort of "import ... as" statement.
> I like qualifying the names from a module, but if I'm using them a lot
> I want to give the module a short name. For instance,
>
> import Tkinter as Tk
>
> would be more comfortable, and is much more clear than:
>
> import Tkinter
> _tk = Tkinter
> del Tkinter
>
> Variants could include:
>
> import package.module as pkgmod # pkgmod is the actual
> # module, not the package
>
> from package import module as pkgmod
> # the same, possibly cleaner
>
> from module import function as func
>
> As I said, I haven't noticed this come up for a while, so maybe I'm
> the only one, but I think this would encourage clarity and
> "localizing" the names of imported modules (adding a leading _ so when
> others "import *" from our modules their namespace isn't polluted too
> much).
>

Now, this I like. I haven't seen this proposal before (or maybe I have
and senility is setting in), but you can now count me in as a proud
supporter of this idea.

Any reason it couldn't be done? What bad things would happen if this
were implemented and "from spam import *" went away?

<except-for-import-spam-as-foo-will-silently-dump-core,-nothing>-ly
y'rs,
Ivan;-)
----------------------------------------------
Ivan Van Laningham
Callware Technologies, Inc.
ivanlan@callware.com
ivanlan@home.com
http://www.pauahtun.org
See also:
http://www.foretec.com/python/workshops/1998-11/proceedings.html
Army Signal Corps: Cu Chi, Class of '70
----------------------------------------------
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
On Fri, 23 Jul 1999, Ivan Van Laningham <ivanlan@callware.com> wrote:
>"Fred L. Drake" wrote:
>> import Tkinter as Tk
>> from module import function as func
>Now, this I like. I haven't seen this proposal before (or maybe I have
>and senility is setting in), but you can now count me in as a proud
>supporter of this idea.

I seem to remember this idea from a few months ago (I checked deja, but
couldn't find it). I also seem to remember Tim or Guido convincing me
that it wasn't really necessary, and things could be done almost as well
another way. Or perhaps I'm just getting old and set in my ways. ;)

>Any reason it couldn't be done? What bad things would happen if this
>were implemented and "from spam import *" went away?

Well, billions of Tkinter programs would break...

(Speaking of which, other weirdness just happened...
>>> import urllib
Traceback (innermost last):
File "<stdin>", line 1, in ?
File "/opt/lib/python1.5/urllib.py", line 25, in ?
import socket
ImportError: No module named socket
>>> print sys.path
Traceback (innermost last):
File "<stdin>", line 1, in ?
NameError: sys
>>> import sys
>>> print sys.path
['', '/opt/lib/python1.5/', '/opt/lib/python1.5/test',
'/opt/lib/python1.5/plat-linux-i386', '/opt/lib/python1.5/lib-tk',
'/opt/lib/python1.5/lib-dynload']
>>> import urllib
>>>

Funky, eh?)

Later,
Blake.

--
One Will. One Dream. One Truth. One Destiny. One Love.
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
Ivan Van Laningham wrote:
>
> Any reason it couldn't be done?

If I remember rightly, Guido's position last time
was that doing it the long-winded way wasn't enough
of a hardship to make it worth adding another language
construct. Not to mention another keyword, which as
we all know would cause the universe to collapse into
a quantum singularity if done prior to Python 2.0.

Greg
Maintainability (was Re: Stackless & String-processing) [ In reply to ]
[Fred L. Drake, "import whatever as something_else"]
> ...
> As I said, I haven't noticed this come up for a while, so maybe I'm
> the only one, but I think this would encourage clarity and
> "localizing" the names of imported modules (adding a leading _ so when
> others "import *" from our modules their namespace isn't polluted too
> much).

New keywords are dead in the water, so maybe you'll find the attached
useful. Make it fancier, e.g. _my_import(globals(),
something_else="whatever") if you like. A version of this used to do that,
but with the functional interface it was too confusing for me.

go-ahead-import-my-day-ly y'rs - tim

def _pvt_import(globs, modname, *items):
"""globs, modname, *items -> import into globs with leading "_".

If *items is empty, set globs["_" + modname] to module modname.
If *items is not empty, import each item similarly but don't
import the module into globs.
Leave names that already begin with an underscore as-is.

# import math as _math
>>> _pvt_import(globals(), "math")
>>> round(_math.pi, 0)
3.0

# import math.sin as _sin and math.floor as _floor
>>> _pvt_import(globals(), "math", "sin", "floor")
>>> _floor(3.14)
3.0
"""

mod = __import__(modname, globals())
if items:
for name in items:
xname = name
if xname[0] != "_":
xname = "_" + xname
globs[xname] = getattr(mod, name)
else:
xname = modname
if xname[0] != "_":
xname = "_" + xname
globs[xname] = mod