getting equal behavior for scripts and modules ?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Mon Oct 12 00:06:46 CEST 2009


On Sun, 11 Oct 2009 19:50:31 +0200, Stef Mientki wrote:

> Now I finally (after 2 years) knowing there's a difference between
> modules and scripts,
> I want to guarantee that I always get the same functional behavior.

You are confused. Scripts *are* modules. What makes a script a script is 
that it is executed from the shell:

$ python ~/scripts/helloworld.py
Hello World.
$

The difference isn't between files which *are* scripts and files which 
*are* modules, but between modules which do something useful when *run as 
a script* versus modules which don't. Recent versions of Python even 
include a switch -m that searches the sys.path for the named module and 
runs the module's .py file as a script.

You don't get the same behaviour between *running* a module and 
*importing* a module because they do different thing. When you say 
"import module" inside the Python environment, the module goes through 
the import machine. When you say "python script.py" in the shell, it 
doesn't.

When you import a module, Python looks to see if it has already been 
imported, and if it has, it returns the module object in the cache. If 
not, then it does a whole lot of magic which includes executing the code 
inside the module. This means that modules get executed only once in any 
session (unless you remove it from the cache). 

When you run a module as a script from the shell, it doesn't go through 
the import machinery, it doesn't get looked up in the cache, and it gets 
executed every time.

The consequence of this is that if you run a module as a script, it gets 
executed. If, in the process of being executed, it imports itself 
(directly or indirectly), the import machinery has to run it again. Hence 
the module gets executed twice.


> I found 2 solutions to realize the above.

Over-engineered overly-complicated non-solution to a non-problem.

The simplest solution is as follows: code that must always be executed 
goes in the body of the module. Code that *only* gets executed when 
running as a script goes under a test:



if __name__ == '__main__':
    # running as a script
    # code goes here
    pass

That code will *only* run when running as a script, and not when you 
import the module. Everything outside such a test will always run. If you 
don't want that distinction, then don't use such a test.



-- 
Steven



More information about the Python-list mailing list