Python Language                
            `exec`と` eval`を使った動的コード実行
        
        
            
    サーチ…
構文
- eval(式[、globals = None [、locals = None]])
- exec(オブジェクト)
- exec(オブジェクト、グローバル)
- exec(オブジェクト、グローバル、ローカル)
パラメーター
| 引数 | 詳細 | 
|---|---|
| expression | 文字列としての式コード、または codeオブジェクト | 
| object | 文字列としてのステートメントコード、または codeオブジェクト | 
| globals | グローバル変数に使用する辞書。 localsが指定されていない場合、これは地元の人々にも使用されます。省略すると、呼び出しスコープの globals()が使用されます。 | 
| locals | ローカル変数に使用されるマッピングオブジェクト。省略すると、代わりに globals渡されたものが使用されます。両方を省略すると、呼び出しスコープのglobals()およびlocals()がそれぞれglobalsおよびlocals使用されglobals。 | 
備考
 execでは、 globalsがlocals (つまり、同じオブジェクトを参照する)場合、コードはモジュールレベルにあるかのように実行されます。 globalsとlocalsが異なるオブジェクトである場合、コードはクラス本体内にあるかのように実行されます。 
 globalsオブジェクトが渡されても__builtins__キーが指定されていない場合、Pythonの組み込み関数と名前は自動的にグローバルスコープに追加されます。実行されたスコープ内でのprintやisinstanceなどの機能の使用を抑止するには、 globals __builtins__というキーを値Noneマップさせます。ただし、これはセキュリティ機能ではありません。 
Python 2固有の構文は使用しないでください。 Python 3の構文はPython 2で動作します。したがって、以下の形式は推奨されません:<s>
-  exec object
-  exec object in globals
-  exec object in globals, locals
execでの文の評価
>>> code = """for i in range(5):\n    print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
evalで式を評価する
>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20
式を複数回プリコンパイルして評価する
 compile組み込み関数を使用して、式をコード・オブジェクトにプリコンパイルすることができます。このコードオブジェクトをevalに渡すことができます。これは、評価されたコードの繰り返し実行をスピードアップします。 compileする3番目のパラメータは、文字列'eval'必要があります。 
>>> code = compile('a * b + c', '<string>', 'eval')
>>> code
<code object <module> at 0x7f0e51a58830, file "<string>", line 1>
>>> a, b, c = 1, 2, 3
>>> eval(code)
5
カスタムグローバルを使用してevalで式を評価する
>>> variables = {'a': 6, 'b': 7}
>>> eval('a * b', globals=variables)
42
プラスとして、このコードでは、誤って外部で定義された名前を参照することはできません。
>>> eval('variables')
{'a': 6, 'b': 7}
>>> eval('variables', globals=variables)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'variables' is not defined
 defaultdict使用すると、たとえば未定義変数をゼロに設定することができます。 
>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables)  # note that 'c' is not explicitly defined
0
ast.literal_evalを使用してPythonリテラルを含む文字列を評価する
文字列、浮動小数点数などのPythonリテラルを含む文字列がある場合、 ast.literal_evalを使用してevalではなくその値を評価できます。これには、特定の構文のみを許可するという追加機能があります。 
>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>
しかし、これは信頼できないユーザによって提供されるコードの実行には安全ではなく、慎重に作成された入力で通訳者をクラッシュさせるのは簡単ではありません
>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5]    21358 segmentation fault (core dumped)  python3
ここで、入力は100万回繰り返された()文字列で、CPythonパーサーでクラッシュを引き起こします。 CPython開発者は、パーサのバグをセキュリティの問題とはみなしません。 
exec、eval、ast.literal_evalを使用して信頼できないユーザーが提供するコードを実行する
 信頼できないユーザーのコードを安全に実行するためにevalやexecを使用することはできません。 ast.literal_evalでもパーサーでクラッシュする傾向があります。悪意のあるコードの実行を防ぐことは時々ありますが、パーサーやトークナイザでのクラッシュの可能性を排除するものではありません。 
信頼できないユーザーがコードを評価するには、サードパーティのモジュールに目を向けるか、独自のパーサーと独自の仮想マシンをPythonで記述する必要があります。