I looked at a number of existing questions about NameError exceptions when scripts are run with exec statements or execfile() in Python, but haven't found a good explanation yet of the following behavior.
I want to make a simple game that creates script objects at runtime with execfile(). Below are 4 modules that demonstrate the problem (please bear with me, this is as simple as I could make it!). The main program just loads a script using execfile() and then calls a script manager to run the script objects:
# game.py
import script_mgr
import gamelib # must be imported here to prevent NameError, any place else has no effect
def main():
execfile("script.py")
script_mgr.run()
main()
The script file just creates an object that plays a sound and then adds the object to a list in the script manager:
script.py
import script_mgr
#import gamelib # (has no effect here)
class ScriptObject:
def action(self):
print("ScriptObject.action(): calling gamelib.play_sound()")
gamelib.play_sound()
obj = ScriptObject()
script_mgr.add_script_object(obj)
The script manager just calls the action() function of each script:
# script_mgr.py
#import gamelib # (has no effect here)
script_objects = []
def add_script_object(obj):
script_objects.append(obj)
def run():
for obj in script_objects:
obj.action()
The gamelib function is defined in a fourth module, which is the troublesome one to be accessed:
# gamelib.py
def play_sound():
print("boom!")
The above code works with the following output:
mhack:exec $ python game.py ScriptObject.action(): calling gamelib.play_sound() boom! mhack:exec $
However, if I comment-out the 'import gamelib' statement in game.py and uncomment the 'import gamelib' in script.py, I get the following error:
mhack:exec $ python game.py ScriptObject.action(): calling gamelib.play_sound() Traceback (most recent call last): File "game.py", line 10, in main() File "game.py", line 8, in main script_mgr.run() File "/Users/williamknight/proj/test/python/exec/script_mgr.py", line 12, in run obj.action() File "script.py", line 9, in action gamelib.play_sound() NameError: global name 'gamelib' is not defined
My question is: 1) Why is the import needed in the 'game.py' module, the one that execs the script? 2) Why doesn't it work to import 'gamelib' from the module where it is referenced (script.py) or the module where it is called (script_mgr.py)?
This happens on Python 2.5.1