global variable not seen (bug?)

Bengt Richter bokr at oz.net
Wed Jan 8 13:54:37 EST 2003


On Wed, 8 Jan 2003 16:51:01 +0100, Michal Vitecek <fuf at mageo.cz> wrote:

> hello everyone,
>
> i've encountered a strange problem with accessing a global variable
> from imported module. the imported module (file imported.py) contains:
> 
>---imported.py start---
> def someFunction():
>    global GLOBAL_VARIABLE
>
>    print GLOBAL_VARIABLE
>---imported.py end---
>
> and now the session copy:
>
>---session start---
>Python 2.2.1 (#4, Sep  4 2002, 13:43:54) 
>[GCC 2.95.3 20010315 (release)] on linux2
>Type "help", "copyright", "credits" or "license" for more information.
>>>> GLOBAL_VARIABLE = 'some value'
>>>> from imported import *
>>>> dir()
>['GLOBAL_VARIABLE', '__builtins__', '__doc__', '__name__', 'someFunction']
>>>> someFunction()
>Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
>  File "imported.py", line 4, in someFunction
>    print GLOBAL_VARIABLE
>NameError: global name 'GLOBAL_VARIABLE' is not defined
>>>> 
>---session end---

The problem is that someFunction() was defined in imported.py
and the global declaration in that function refers to what's
global from there, namely the module scope of imported.py,
and GLOBAL_VARIABLE is not defined there.

Nor did it become defined _there_ when you interactively
typed
    GLOBAL_VARIABLE = 'some value'

because the module for interaction is  "__main__", not "imported".

Since you did a "from imported import *", you can't reach it's global
space by normal means, but if you just import it, you can then write

   imported.GLOBAL_VARIABLE = 'some other value'

Note what happens, starting out like you did:

 >>> GLOBAL_VARIABLE = 'some value'
 >>> from imported import *
 >>> dir()
 ['GLOBAL_VARIABLE', '__builtins__', '__doc__', '__name__', 'someFunction']
 >>> someFunction()
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "imported.py", line 3, in someFunction
     print GLOBAL_VARIABLE
 NameError: global name 'GLOBAL_VARIABLE' is not defined

Ok, now we import normally, so we can access the module via its name
 >>> import imported
 >>> dir(imported)
 ['__builtins__', '__doc__', '__file__', '__name__', 'someFunction']

Note that there is no GLOBAL_VARIABLE in there, which is why the functin got NameError.

Now we'll set a value in that global space:
 >>> imported.GLOBAL_VARIABLE = 'some other value'

And try the function again:
 >>> someFunction()
 some other value

No NameError ;-)

Looking at the interactive namespace:
 >>> dir()
 ['GLOBAL_VARIABLE', '__builtins__', '__doc__', '__name__', 'imported', 'someFunction']

Looking in the module's namespace:
 >>> dir(imported)
 ['GLOBAL_VARIABLE', '__builtins__', '__doc__', '__file__', '__name__', 'someFunction']

They both have GLOBAL_VARIABLE bindings now.

 >>> GLOBAL_VARIABLE
 'some value'

 >>> imported.GLOBAL_VARIABLE
 'some other value' 

The 'global' declaration in the function does not reserve a space or bind the name globally,
it just says where to go when the name is encountered in the same scope. It is only needed
if you want to assign to a global from the function (without the declaration it merely
makes a local binding).

If you had had a GLOBAL_VARIABLE assignment in the "imported" module, you would have gotten
that variable printed, because the function would be looking in the module. But with the
"from imported import *" style of importing, you would get name binding in the interactive
space pointing the the GLOBAL_VARIABLE in the imported module, but you might get fooled again
if you tried to change the value with an unqualified name, since you would only be rebinding
the name in the interactive space, not the one in the module. Thus you could print the
new value interactvely, but the function would still access the binding in the module. We
can show that, continuing from above:

Looking at status quo:
 >>> GLOBAL_VARIABLE # the interactive one
 'some value'
 >>> someFunction()
 some other value

Set a new interactive value:
 >>> GLOBAL_VARIABLE = 'a new interactive value'

See if the function sees it:
 >>> someFunction()
 some other value
Nope.

Do we see it interactively?
 >>> GLOBAL_VARIABLE # the interactive one
 'a new interactive value'
Yep.

Regards,
Bengt Richter




More information about the Python-list mailing list