我在Python中使用exec語句或execfile()運行腳本時查看了一些關於NameError異常的現有問題,但尚未找到有關以下行爲的良好解釋。爲什麼不導入在使用execfile()運行的python腳本中阻止NameError?
我想做一個簡單的遊戲,在運行時用execfile()創建腳本對象。下面是4個模塊來演示這個問題(請耐心等待,這很簡單,我可以做到!)。主程序只是用來加載使用的execfile()的腳本,然後調用腳本管理器來運行腳本對象:
# 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()
該腳本文件剛剛創建播放聲音的對象,然後將對象添加到列表中腳本管理器:
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)
腳本管理器只是調用每個腳本的動作()函數:
# 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()
的gamelib函數的第四模塊中定義,這是被訪問的麻煩之一:
# gamelib.py
def play_sound():
print("boom!")
上面的代碼與下面的輸出工作:
mhack:exec $ python game.py ScriptObject.action(): calling gamelib.play_sound() boom! mhack:exec $
但是,如果我註釋掉的「進口gamelib」聲明game.py並取消在script.py「進口gamelib」,我得到以下錯誤:
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
我的問題是:1)爲什麼需要進口的「game.py」模塊中,該高層腳本中的一個? 2)爲什麼它不能從引用它的模塊(script.py)或它被調用的模塊(script_mgr.py)中導入'gamelib'?
這發生關於Python 2.5.1
我知道全局和本地參數,但我仍然不確定如何最好地使用它們。你對環境的引用有助於我更好地理解,但是我仍然不明白爲什麼script.py中的導入不起作用 - 是不是也將它放入環境中? – 2010-02-28 00:05:50
通過打印出全局變量和當地人在測試後更新了我的答案。希望它有幫助;) – Yukiko 2010-02-28 11:50:13
是的,它確實有幫助!在您觀察到導入後對全局變量和本地變量的影響之後,我添加了一些調試代碼來打印出全局變量和本地變量,這真的讓事情變得清晰。我會接受你的答案,但也會對我的結果發佈後續答案。 – 2010-02-28 16:00:03