Re: module.__self__ and "on import" conventions

Doug Moen (dmoen@io.org)
Wed, 15 Dec 93 21:42 WET

Steve Majewski:
> I'll entertain suggestions for other methods to solve the same
> problem:
>
> I have gotten used to several of my modules doing some action
> when run as a script, vs when imported as a module. Typically,
> this is either a test of the module, or an application that was
> the main reason for writing it ( although I often end up using
> the functions in that module for other things, later. ).
>
> Frequently, the last piece of code in the module is somthing like:
>
> import sys
> if sys.argv[1:] :
> do_something( sys.argv[1:] )
>
> - or perhaps -
>
> for arg in sys.argv[1:]:
> do_something( arg )
>
>
> This distinguished between running: 'module.py args... ' from the
> shell, versus typing 'import module' from interactive python, but
> it get's confused when imported from another module that tries to
> do the exact same thing.

I've been doing some serious thinking about changes to Python (both the
language and the implementation) that would significantly speed up the
interpreter.

One of my (many) ideas is to run a code optimization pass *after*
a module has initialized itself. The reason for doing it then is that
(with suitable language changes) we could guarantee that all global bindings
have been established. The code optimizer, could, for example, determine
that a particular call to 'range' is in fact bound to the builtin function
'range', and it could use this information to emit efficient code for
for i in range(1,10):

Unfortunately, there is no such thing as "after a module has initialized
itself" for Python scripts, because the initialization phase is identical
to running the script. So, one of the language changes required to make
my idea fly is this: a Python script is now required to contain a function
called 'main', which is called with the argument 'argv'.

This change seems to provide a nice solution to Steve's problem.
Steve has code that he wants executed when a module is run as a script,
but not when it is imported. Under the above proposal, all he has to
do is put this code into the function 'main'.

My proposal also provides the general ability to write modules that
import scripts, then create an argument list for that script, then
run the script with that argument list. For example,
import myscript
args = [ ... ]
myscript.main(args)

Actually, this proposal can be implemented without losing backward
compatibility. We change Python so that when it runs a script,
it first initializes it, then checks for a binding called 'main',
and calls it with sys.argv if 'main' exists. If there are already
a lot of scripts containing functions called 'main', then we modify
this proposal to use a different name, like '__main__' for instance.
That way, no existing code is broken.