Oddball python import issue?
It seems when I have the import within my function I get some strange behavior. For lack of cooperative blog formatting, here’s a link to the code and the results. I tested this with python 2.5.2 and 2.6.2.
Now that I’ve pinpointed the issue I can easily work around it. But .. I’m still curious if anyone can tell me what is going on? Is this a feature? Or is there a bug at work here?
July 16th, 2009 at 12:35 pm
It’s not an import issue. It’s a sharing of globals across modules issue. You can’t do that! No accessing globals across module boundries! Each module has it’s own global symbol table.
But you can use any module you want to store your variable in.
Behold!
# test.py
import test2
def add_stuff(v):
import test3
test3._textures.append(v)
print test3._textures
def main():
import test2
import test3
print test3._textures
test3._textures = []
print test3._textures
add_stuff(‘from test’)
test2.do_whatever()
if __name__ == ‘__main__’:
main()
# test2.py
from test import add_stuff
def do_whatever():
add_stuff(‘from test2’)
# test3.py
_textures = None
You could even put ‘pass’ in test3.py and let Python autocreate the slots you need.
July 16th, 2009 at 2:20 pm
When you run test as the main script it is in sys.modules as __main__ and *not* as test. When you do “import test” in test2 you import a *new* copy of the test module – this time as ‘test’ instead of __main__.
add_stuff is imported from the test module not the __main__ module.
You could fix it in test by adding the following to the “if __name__ == ‘__main__’:” block:
sys.modules[‘test’] = sys.modules[‘__main__’]
Michael
July 16th, 2009 at 2:46 pm
Michael’s right on. Here’s another approach you can take to avoid this. In test.py, start off with this:
if __name__ == ‘__main__’:
import test
raise SystemExit(test.main())
July 16th, 2009 at 2:47 pm
Michael already explained it clearly. The only thing I can add is that if you can visualize what is going on by adding a print add_stuff.__module__ to add_stuff itself:
def add_stuff(v):
print add_stuff.__module__
_textures.append(v)
July 16th, 2009 at 4:45 pm
@Michael – Cool, thanks for explaining this behavior. I gotta admit it isn’t the intuitive behavior I usually expect from python 😉
-Phil
July 16th, 2009 at 7:53 pm
Of course, Michael got there first, but I wanted to comment that it stays intuitive if you stick to the “dont import scripts” rule. That is, if you designate a .py as a “script” it is mentally distinct from a “module” in the usually understood sense. Of course, this is one-way, because modules *can* double as scripts, so you could probably get around this just by running it as:
python -m test
July 16th, 2009 at 9:33 pm
All said and done, since this was supposed to be just a quick-n-dirty script anyways, I combined both files into one, as the “right” solution would have meant breaking the file into even more parts, which was even less desirable.