1

I am looking for a pythonic way to access a global variable(profit_benchmark) which is defined inside a __init__.py file and it's value modified in one of the modules(routines.py) and now I wanted to access profit_benchmark with modified value in another module(network.py)

Here is my folder structue:

enter image description here

__init__.py

profit_benchmark = 50

routines.py

from so import profit_benchmark
profit_benchmark = 60

network.py

from so import profit_benchmark
print(profit_benchmark)

Output:

50

I am expecting an output of 60 because variable profit_benchmark modified in routine.py

My Question: How can I access the new value of profit_benchmark variable in network.py so that ouput will be 60

7
  • 2
    The Pythonic way would be not to rely on global mutable state, and that is just a general programming best-practice. Anyway, your import creates a new local variable . You can just import so and use so.profit_benchmark Commented Dec 11, 2019 at 16:09
  • @juanpa.arrivillaga so how do i know if global variable is changed if we don't rely on that. what's the best practice to know the modified status of global variable. Commented Dec 11, 2019 at 16:12
  • min2bro: @juanpa.arrivillaga just told you the "best practice". Commented Dec 11, 2019 at 16:13
  • @martineau that doesn't work importing profit_benchmark from so still gives the old value i.e. 50 . I tried so.profit_benchmark Commented Dec 11, 2019 at 16:16
  • 1
    @min2bro this was juanpa's adivce not martineau's one, and it seems you didn't read it well enough - he told you to replace the from so import profit_benchmark statements with import so and then to always use so.profit_benchmark - and this WILL work. Commented Dec 11, 2019 at 16:19

1 Answer 1

2

First thing: Python doesn't have real globals, only module-level globals - each module is a distinct namespace and a global is only 'global' to the module it's defined in.

Second thing: the import statement is nothing like a C or PHP include - it doesn't "copy" the whole imported module in the importing one, but loads the imported module (if it hasn't been loaded already) and make it available in the importing namespace

Actually, this:

import so

is a shortcut for

from importlib import importmodule
so = importmodule("so")

and this:

from so import profit_benchmark

is a shortcut for

from importlib import importmodule
so = importmodule("so")
profit_benchmark = so.profit_benchmark
del so

As juanpa (briefly) explained, in this second case, what happens is that you end up with two names (so.profit_benchmark and your_importing_module.profit_benchmark) both pointing to the same object.

Now Python variables aren't C-style memory location, they are name=>object entries in a namespace (mostly, key:value pairs in a dict). Assignment actually just make the assigned named point to another object, so when you do

from so import profit_benchmark
profit_benchmark = 42

the first statement creates the name "profit_benchmark" in the current namespace and binds it to the same object as what so.profit_benchmark points to, and the second statement rebinds the current namespace's profit_benchmark name to the 42 int object, leaving so.profit_benchmark totally unchanged. All this (and much more very useful things to know) is explained in great depths in this Ned Batchelder's article.

On the other hand when you do

import so
so.profit_benchmark = 42

the name you are rebinding is effectively so's "global" profit_benchmark - which has actually become an attribute of the so module object (at runtime, modules are objects too), so any other module reading so.profit_benchmark will now get the updated value.

This being said: you asked for "the pythonic way", and the pythonic way is actually to avoid mutable global state as much as possible (and that's one of the reasons why python's "globals" aren't truly globals). And the fact is that once you get into the habit of using pure functions as much as possible and classes when you need to have some shared state between a state of functions, you realize you can write very large programs without a single "writable" global (nb: read-only globals are of course perfectly ok, the problems begin when you start mutating or - even worse - rebinding globals).

So the question is: why do you think you need a writable global at all ? There are many ways to avoid them, but the "correct" solution(s) depends on the concrete use case, which you say nothing about.

Sign up to request clarification or add additional context in comments.

3 Comments

You will agree with me that there are cases where you would need to update the global variables just to let the downstream process to be aware of the current status of the global variable. For example: I would like to do a intermittent health checkup on one of the services and want to pass this status every state. best way to store the health in a global variable and pass on rather than hitting the server at every stage
So what I mean is I really don't understand that why everyone is advocating for not modifying the global variable. It's all about the use case that you have in hand
@min2bro I won't agree with anything until I've seen the specs and the code - there are many ways to skin a cat ;-) And everyone is just stating what they learned by experience: the less mutable global state you have, the better. For more "restricted" mutable state, you have classes and objects. And of course functions arguments...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.