Reputation: 401
In short: in Python it is too easy to create multiple instances of the same module, each instance having its own set of global variables.
I need to add a check to the module to detect such multiple instantiation and raise an exception.
My problem is the same as this one: Module imported multiple times
This is the smallest directory structure to reproduce the problem:
/test/a/__init__.py
/test/a/aa.py:
print "aa: __name__: ", __name__
/test/b/b.py:
from a import aa
import aa
Then
export PYTHONPATH=/test:/test/a
python /test/b/b.py
prints:
aa: __name__: a.aa
aa: __name__: aa
So, module aa.py was imported twice with different names.
Needless to say that module aa.py will get 2 sets of global variables, which screws up all the logic inside this module.
Of course, in the trivial example above it is easy to detect error by eyes, but in complex project with multiple subdirectories, these errors keep popping up regularly.
So, I need some really global variable or a process-wide store or something like that. Any idea?
Edit: Bibhas asked for an example of multiple instances of the same global variable. Here it is:
/test/a/__init__.py
/test/a/aa.py:
print "aa: __name__: ", __name__
import thread
import time
test_var = __name__
def test():
for i in range(0,5):
print "aa thread: test_var: ", test_var
time.sleep(1)
thread.start_new_thread( test, () )
/test/b/b.py:
print "b: __name__: ", __name__
from a import aa
import aa
import time
time.sleep(10)
Now running
export PYTHONPATH=/test:/test/a
python /test/b/b.py
prints:
aa: __name__: a.aa
aa: __name__: aa
aa thread: test_var: aa
aa thread: test_var: a.aa
aa thread: test_var: aa
aa thread: test_var: a.aa
...
So, it is clear that there are 2 instances of variable test_var. If I will try to implement a singleton in this module, there will be 2 instances of this singleton, etc.
Edit2: So, solution suggested by Guy L is something like:
/test/a/aa.py:
import os
if "aa.py" in os.environ:
raise Exception("Duplicate instantiation of aa.py")
os.environ["aa.py"] = __name__
It seems to work OK (as long as I do not call import on multiple threads). Anybody have a better one?
Upvotes: 2
Views: 1641
Reputation: 1
The problem is that you're making the module available from two different entries in your path.
That's something that shouldn't happen, you should have your entire project dir in the path, and all module imports done regardless of location inside the project use the full path for importing, so, instead of your example, it should be:
export PYTHONPATH=/test
python /test/b/b.py
And you'll always need to use the imports like on the first line of b.py:
from a import aa
Upvotes: 0
Reputation: 2954
It's an ugly workaround but you can use os.environ[] to set enviorment variables. I don't like it that much since it contaminates the eviroment variables.
Here is how you can set those: http://code.activestate.com/recipes/159462-how-to-set-environment-variables/
Good luck, Guy
Upvotes: 2