Python で exec ステートメントまたは execfile() を使用してスクリプトを実行した場合の 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)
スクリプト マネージャーは、各スクリプトの action() 関数を呼び出すだけです。
# 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 関数は 4 番目のモジュールで定義されています。これは、アクセスするのが面倒なモジュールです。
# gamelib.py
def play_sound():
print("boom!")
上記のコードは、次の出力で機能します。
mhack:exec $ python game.py ScriptObject.action(): gamelib.play_sound() の呼び出し ブーム! mhack:exec $
ただし、game.py の「import gamelib」ステートメントをコメントアウトし、script.py の「import gamelib」のコメントを外すと、次のエラーが発生します。
mhack:exec $ python game.py ScriptObject.action(): gamelib.play_sound() の呼び出し トレースバック (最新の呼び出しが最後): ファイル「game.py」の 10 行目 主要() ファイル「game.py」、8 行目、メイン script_mgr.run() ファイル "/Users/williamknight/proj/test/python/exec/script_mgr.py"、12 行目、実行中 obj.action() ファイル「script.py」、9 行目、動作中 gamelib.play_sound() NameError: グローバル名 'gamelib' が定義されていません
私の質問は次のとおりです。1)スクリプトを実行する「game.py」モジュールでインポートが必要なのはなぜですか? 2) 「gamelib」が参照されているモジュール (script.py) または呼び出されているモジュール (script_mgr.py) から「gamelib」をインポートできないのはなぜですか?
これは Python 2.5.1 で発生します