using 'global' across source files.

Mark Jackson mjackson at wc.eso.mc.xerox.com
Wed Jan 3 10:18:06 EST 2001


Bram Stolk <bram at sara.nl> writes:
> Mark Jackson wrote:
> > 
> > Bram Stolk <bram at sara.nl> writes:
> > > According to the manuals, it should simply be in the namespace
> > > '__main__', but that doesnt work either.
> > 
> > You're misreading the manuals.  Can you tell us how you drew this
> > conclusion?  (Possibly the manuals could be clearer.)
> 
> Well, because in execframes.html, it can be read that:
> "The main module for a script is always called __main__"

You're misinterpreting the significance of the term "main module"; it
*doesn't* denote, for example, "a comprehensive namespace that contains
all names."  It just refers to the top-level namespace (in a tree-, or
rather hedge-like sense):  what you have direct access to when working
in the interpreter, or alternatively where a script executes.
Observe:

    yngvi> cat eggs.py
    print "Hi, I'm eggs"
    print dir()
    print __name__

    yngvi> python -i eggs.py
    Hi, I'm eggs
    ['__builtins__', '__doc__', '__name__']
    __main__

    >>> import eggs
    Hi, I'm eggs
    ['__builtins__', '__doc__', '__file__', '__name__']
    eggs
    >>> 

If you don't understand this behavior you don't understand Python
namespaces well enough.  Rereading section 9.2 of the tutorial ("Python
scopes and namespaces") may be helpful.

> And because I can do:
> dir(__builtins__)
> 
> I thought, why the heck doesn't dir(__main__) work?

As noted elsewhere you have to import __main__ into the local
namespace.  In the interpreter you can simply incant dir() without an
argument, which as seen above refers to the local namespace (which in
that case is, of course, __main__).

> Also, I had no idea that using a 'global val' cmd, creates 
> another copy of val, which I deduct from your comment:
> "But the val that change_val changes is defined in funcs.py, 
> NOT prog.py"

Wrong deduction.  Names are not copied.  (Objects may be copied; global
does neither.)  In the code to which I was referring you had created
two names 'val'; one in prog.py and one in funcs.py.  Here it is:

    # funcs.py
    
    def change_val() :
      global val
      val = val * 2
    
    
    
    # prog.py
    
    val = 100
    
    import funcs
    
    
    funcs.change_val()
    print val

In prog.py the name val will be created by the execution of "val = 100"
(which happens when prog.py is executed as a script, or when "import
prog" creates a module).  In funcs.py it will be created by the
execution of "val = val * 2" during invocation (not definition) of
change_val(); because of the preceding "global val" the name will
appear in the module namespace rather than in the local namespace for
the function change_val.  Study this until it ceases to surprise:

    yngvi> cat funcs.py
    def change_val():
	    global val
	    val = 2
	    print dir()
    
    def no_change():
	    val = 5
	    print val
	    print dir()

    yngvi> python -i funcs.py
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'change_val', 'no_change']
    >>> change_val()
    []
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'change_val', 'no_change', 'val']
    >>> print val
    2
    >>> no_change()
    5
    ['val']
    >>> print val
    2
    >>> 

The function change_val has no local names, but its invocation creates
one in the surrounding namespace (__main__ in this case).  The function
no_change has, while executing, a local name, val, which is entirely
unrelated to __main__.val.  (One could change either 'val' to
'throatwarblermangrove' without effect.)

> I thought that python's 'global' acted like C's 'extern' cmd,
> meaning, that 'global val' does NOT define/create 'val',
> only refers to a val that exists somewhere else.
> 
> I don't know wether me thinking this is due to my poor
> understanding, or the quality of the manuals, though.
> 
> Anyway, to clear things up: what I wanted to achieve is
> pretty straightforward: I can use "global vars" that
> reside outside a func body, but in the same module.
> I wanted one step further: use "even more global vars"
> that reside outside a func body, and even outside the
> current module (read: sourcefile).

See other advice (for example, from D-man) on this subject.

-- 
Mark Jackson - http://www.alumni.caltech.edu/~mjackson
	The power of accurate observation is frequently called
	cynicism by those who don't have it.
			- George Bernard Shaw





More information about the Python-list mailing list