10

In my main class I use a global variable ADDRESS that is defined in another file called config.py. I want to change the value of ADDRESS from within my main class, by calling a function in config.py.

In my main class I have:

from config import ADDRESS, change_address
change_address("192.168.10.100")
print("new address " + ADDRESS)

In my config file I have the following:

ADDRESS = "0.0.0.0"

def change_address(address):
    global ADDRESS
    ADDRESS = address
    print("changed address to: " + ADDRESS)

The print statement in my config file correctly prints the new address of 192.168.10.100. However, the print statement in my main class prints 0.0.0.0. What am I missing here?

crusarovid
  • 501
  • 1
  • 5
  • 17
  • Your `import` binds a new local variable `ADDRESS` to the string that the `ADDRESS` variable in config refers to. When you call `change_address()` the `ADDRESS` variable in config now refers to a different string. Your own local variable still refers to the original string. – quamrana Dec 05 '17 at 19:12

2 Answers2

11

All that from config import ADDRESS, change_address does is take ADDRESS and change_address from your config module's namespace and dumps it into your current module's name-space. Now, if you reassign the value of ADDRESS in config's namespace, it won't be seen by the current module - that's how name-spaces work. It is like doing the following:

>>> some_namespace = {'a':1}
>>> globals().update(some_namespace)
>>> a
1
>>> some_namespace
{'a': 1}
>>> some_namespace['a'] = 99
>>> a
1
>>> some_namespace
{'a': 99}

The simplest solution? Don't clobber name-spaces:

import config
config.change_address("192.168.10.100")
print("new address " + config.ADDRESS)
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • 5
    You were quicker ;) I just wanted to add this link, since it describes this common problem: https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules – gonczor Dec 05 '17 at 19:16
  • worked perfectly :) thank you @gonczor. Although not a duplicate question I believe, I found same solution here: https://stackoverflow.com/questions/3536620/how-to-change-a-module-variable-from-another-module – crusarovid Dec 05 '17 at 20:14
0

I would recommend that you try not to change the global state in a module. Instead, I would re-write the code such that ADDRESS in config.py doesn't change. If the configuration for your application can change from invocation to invocation I would change config to be something like:

ADDRESS = '0.0.0.0'

def get_default_config():
    return {'address': ADDRESS, 'some_other_config_value': 'foo'}

Then in main I would do:

app_config = config.get_default_config()
app_config = "192.168.10.100"
print("new address " + app_config['address']

As a general rule it isn't a good idea to change the value of variables/constants in other modules.

NOTE: You could also create a config class as well, so that you could access configuration values like config.address.

I recommend that you read the stackexchange post Why is Global State so Evil?

aquil.abdullah
  • 3,059
  • 3
  • 21
  • 40