質問

pygameとbox2dを使用してゲームエンジンを記述しています。キャラクタービルダーでは、キーダウンイベントで実行されるコードを記述できるようにします。

次のようなコードを記述できるテキストエディターをキャラクタービルダーに含めるつもりでした。

if key == K_a:
    ## Move left
    pass
elif key == K_d:
    ## Move right
    pass

テキストエディターの内容を文字列として取得し、このCharacterのメソッドのメソッドでコードを実行したい:

def keydown(self, key):
    ## Run code from text editor

それを行う最良の方法は何ですか?

役に立ちましたか?

解決

eval(string) これを行うメソッド。

定義

eval(code、globals = None、locals = None)
コードは単なる標準のPythonコードです。つまり、適切にインデントする必要があります。

グローバルには、カスタムの __ builtins __ を定義できます。これは、セキュリティの目的に役立ちます。

eval("print('Hello')")

hello をコンソールに出力します。使用するコードのローカル変数とグローバル変数を指定することもできます。

eval("print('Hello, %s'%name)", {}, {'name':'person-b'})

セキュリティの問題

ただし、注意してください。ユーザー入力が実行されます。考慮:

eval("import os;os.system('sudo rm -rf /')")

それを回避する方法はいくつかあります。最も簡単なのは次のようなことです:

eval("import os;...", {'os':None})

ハードドライブを消去するのではなく、例外をスローします。あなたのプログラムはデスクトップですが、人々がスクリプトを再配布した場合、これは問題になる可能性があります。

奇妙な例

これは eval をかなり奇妙に使用する例です。

def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'

eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))

これがeval行で行うこと:

  1. 現在のモジュールに別の名前を付けます(スクリプトの contrivedExample になります)。コンシューマは contrivedExample.hello()をすぐに呼び出すことができます。)
  2. hi hello
  3. を指していると定義します
  4. その辞書を、実行中のモジュールの現在のグローバルのリストと組み合わせました。

FAIL

exec ステートメントを実際に使用する必要があることがわかりました(コメントありがとう!)。おっと。改訂された例は次のとおりです。


exec 定義

(これはおなじみですね!) Execはステートメントです:
exec" code" [範囲内] scopeは、ローカル変数とグローバル変数の両方の辞書です。これが指定されていない場合、現在のスコープで実行されます。

コードは単なる標準Pythonコードです。つまり、適切にインデントする必要があります。

exec の例

exec "print('hello')"

hello をコンソールに出力します。使用するコードのローカル変数とグローバル変数を指定することもできます。

eval "print('hello, '+name)" in {'name':'person-b'}

exec セキュリティ上の問題

ただし、注意してください。ユーザー入力が実行されます。考慮:

exec "import os;os.system('sudo rm -rf /')"

ステートメントの印刷

コメンターも指摘しているように、 print は3.0より前のすべてのバージョンのPythonのステートメントです。 2.6では、__ future__ import print_statement からを入力して動作を変更できます。それ以外の場合は、次を使用します。

print "hello"

の代わりに:

print("hello")

他のヒント

他の人が指摘したように、テキストを文字列にロードして、 exec" codestring" を使用できます。既にファイルに含まれている場合、 execfile を使用すると、ファイルをロードする必要がなくなります。

1つのパフォーマンスノート:Pythonソースの解析とコンパイルは時間がかかるため、コードを複数回実行することは避けてください。すなわち。持っていない:

def keydown(self, key):
    exec user_code

ソースをコードオブジェクトにコンパイルして( compile()で実行するか、それ以上に、保持する関数を作成し、一度だけビルドすることで、これを少し改善できます。ユーザーに" def my_handler(args ...)"を記述することを要求するか、自分で先頭に追加して次のようにします:

user_source = "def user_func(args):\n" + '\n'.join("    "+line for line in user_source.splitlines())

d={}
exec user_source in d
user_func = d['user_func']

その後:

if key == K_a:
   user_func(args)

eval() を使用できます。

evalまたはexec。プログラミングする前に、Pythonライブラリリファレンスを必ずお読みください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top