Ich habe mir eine Reihe von Fragen zu NameError-Ausnahmen angesehen, wenn Skripte mit exec-Anweisungen oder execfile() in Python ausgeführt werden, habe aber noch keine gute Erklärung für das folgende Verhalten gefunden.
Ich möchte ein einfaches Spiel erstellen, das Skriptobjekte zur Laufzeit mit execfile() erstellt. Im Folgenden finden Sie 4 Module, die das Problem veranschaulichen (bitte haben Sie Geduld mit mir, das ist so einfach, wie ich es machen konnte!). Das Hauptprogramm lädt einfach ein Skript mit execfile() und ruft dann einen Skriptmanager auf, um die Skriptobjekte auszuführen:
# 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()
Die Skriptdatei erstellt einfach ein Objekt, das einen Ton abspielt, und fügt das Objekt dann einer Liste im Skriptmanager hinzu:
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)
Der Skriptmanager ruft einfach die action()-Funktion jedes Skripts auf:
# 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()
Die gamelib-Funktion ist in einem vierten Modul definiert, auf das der Zugriff problematisch ist:
# gamelib.py
def play_sound():
print("boom!")
Der obige Code funktioniert mit der folgenden Ausgabe:
mhack:exec $ python game.py
ScriptObject.action(): calling gamelib.play\_sound()
boom!
mhack:exec $
Wenn ich jedoch die Anweisung "import gamelib" in game.py auskommentiere und die Anweisung "import gamelib" in script.py entkommentiere, erhalte ich die folgende Fehlermeldung:
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
Meine Frage ist: 1) Warum wird der Import im Modul 'game.py' benötigt, dem Modul, das das Skript ausführt? 2) Warum funktioniert es nicht, "gamelib" aus dem Modul zu importieren, in dem es referenziert wird (script.py) oder aus dem Modul, in dem es aufgerufen wird (script_mgr.py)?
Dies geschieht mit Python 2.5.1