Search code examples
pythonipythongloballocal

Python Assumes Variable is Local


First I will say that this is an assignment and the behavior required is not under my control. I am creating a script called globaltest.py that should act exactly the same if the file is run or if the function within the file is called. I am doing both from ipython. It should create a dictionary called station_dict that can be accessed in the ipython console or seen with the whos command.

from globaltest import file_to_dict
file_to_dict()

This should make a variable called station_dict when the function is run.

And here is the behavior when the script is simply being run:

Run globaltest

This should also create a dictionary called station_dict.

The issue is calling and using the function file_to_dict does not create the variable while just running the file does. Here is my code. Thanks for any help.

#!//bin/env python3

def main():

    global station_dict

    station_dict = {}

    station_dict['foo'] = 'bar'

def file_to_dict():

    global station_dict

    station_dict = {}

    station_dict['foo'] = 'bar'

if __name__ == '__main__':
    main()

Here is the bad output as a result of using the function:

Python 3.4.5 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:47:47)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from globaltest import file_to_dict

In [2]: file_to_dict()

In [3]: whos
Variable       Type        Data/Info
------------------------------------
file_to_dict   function    <function file_to_dict at 0x7f869f39cea0>

Here is the good output as a result of running the program:

Python 3.4.5 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:47:47)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: run globaltest.py

In [2]: whos
Variable       Type        Data/Info
------------------------------------
file_to_dict   function    <function file_to_dict at 0x7fb92b7df8c8>
main           function    <function main at 0x7fb92b7df0d0>
station_dict   dict        n=1

Solution

  • There are two things going on here:

    1. What Python calls "global" is not really global, it's module-level (i.e. in the module namespace). So when you run file_to_dict, station_dict becomes set in globaltest's namespace, though that namespace is not bound (i.e. not imported), so station_dict is inaccessible. To access it, you could do:

      import globaltest
      globaltest.station_dict
      
    2. IPython's %run runs the code in the interpreter's namespace.

    That said, I don't know how to achieve what you want. As far as I know, a function can't set variables in its calling namespace, although it might be possible by getting into hacky stuff like inspect.

    If it helps, you could read about sharing variables between modules.