Beautiful Python

John J. Lee jjl at pobox.com
Wed Dec 28 16:37:36 EST 2005


news at absamail.co.za writes:
[...]
> > Sometimes putting import statements at the beginning is not feasible
> > (i.e. only when some condition has been met), as importing has some
> > impact on program execution (importing executes code in imported
> > module). This does not resemble Java imports (I don't know Perl).
> > 
> > -- 
> Wow ?!   I've only started looking at python but that sounds like very
> dangerous programming !  Can you give an example.

Leaving aside that the first import of a Python module *always*
executes code -- even if that code be something like a 'def' statement
(I assume that's NOT what worried you), you're certainly correct that
anything anywhere near this sort of thing is harmful:

#-----------8<-------------
# this is file mymodule.py

def good():
    print "mmmmm"

evil = good
evil()  # because importing shouldn't have side-effects
#----------->8-------------


Though you may perfectly well do this:

#-----------8<-------------
# this is file mymodule2.py

try:
    from goodstuff import good
except ImportError:
    def good():
        print "mmmmm"
#----------->8-------------

(and of course, if statements are just as acceptable in that example
as try/except -- though try/except is often handier than if/else in
this sort of case)


Or this, using the standard idiom to have a module work also as a
script:

#-----------8<-------------
# this is file mymodule3.py

def good():
    print "mmmmm"

if __name__ == "__main__":
    # only executed if we're running as a script
    good()
#----------->8-------------


Just in passing, this is the standard idiom when you want to change
some global setting:

#-----------8<-------------
# this is file weird.py

def enable_weird_shit():
    ...
#----------->8-------------

One then does:

import weird; weird.enable_weird_shit()


This last style is used, eg. by things like module cgitb (replaces the
standard global traceback handler with a different one) and PTL
(introduces a global import hook of some kind for .ptl template
files).


> BTW this topic relates to a recent point raised by the C man's
> [I think Richie, dated ca. 1973] crit of Pascal. He said that
> Pascal's restriction of not being able to declare globals, near
> where they were needed, was bad.  And I thought so too, before I
> considered that the programmer must KNOW that they are global.
> Ie. the ability to declare them at a 'nice' place is just syntactic
> sugar, hiding the reality the globals are bad, and have to be avoided
> and respected.

Maybe so (though not sure I understand exactly what you're saying),
but not relevant to the question at hand, so far as I can see: Python
import statements inside a function or class scope do NOT contaminate
the global namespace.  sys.modules (which is global state) may grow a
new key/value pair, but that's a different thing, and non-harmful.

One good thing about local imports is that you can keep a function or
class self-contained, so it can easily be moved to another module
without import changes.

A bad thing is that it becomes less easy to see at a glance what a
module's dependencies are (but a quick search for the string 'import'
is all that's needed there).

I always used to stick to the 'imports at the top' style.  Having been
introduced to the other way of doing it at work, I still don't have an
opinion on whether it's just a matter of mix-n-match (applying good
taste and experience to pick which style to use for each import
statement) or whether it's best to stick rigidly to one style or the
other.  So I just try to stick to the "When in Rome" principle, and
follow local conventions, unless it seems stupid to do so.


John




More information about the Python-list mailing list