サーチ…


構文

  • eval(式[、globals = None [、locals = None]])
  • exec(オブジェクト)
  • exec(オブジェクト、グローバル)
  • exec(オブジェクト、グローバル、ローカル)

パラメーター

引数詳細
expression 文字列としての式コード、またはcodeオブジェクト
object 文字列としてのステートメントコード、またはcodeオブジェクト
globals グローバル変数に使用する辞書。 localsが指定されていない場合、これは地元の人々にも使用されます。省略すると、呼び出しスコープのglobals()が使用されます。
locals ローカル変数に使用されるマッピングオブジェクト。省略すると、代わりにglobals渡されたものが使用されます。両方を省略すると、呼び出しスコープのglobals()およびlocals()がそれぞれglobalsおよびlocals使用されglobals

備考

execでは、 globalslocals (つまり、同じオブジェクトを参照する)場合、コードはモジュールレベルにあるかのように実行されます。 globalslocalsが異なるオブジェクトである場合、コードはクラス本体内にあるかのように実行されます。

globalsオブジェクトが渡されても__builtins__キーが指定されていない場合、Pythonの組み込み関数と名前は自動的にグローバルスコープに追加されます。実行されたスコープ内でのprintisinstanceなどの機能の使用を抑止するには、 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を使用して信頼できないユーザーが提供するコードを実行する

信頼できないユーザーのコードを安全に実行するためにevalexecを使用することはできません。 ast.literal_evalでもパーサーでクラッシュする傾向があります。悪意のあるコードの実行を防ぐことは時々ありますが、パーサーやトークナイザでのクラッシュの可能性を排除するものではありません。

信頼できないユーザーがコードを評価するには、サードパーティのモジュールに目を向けるか、独自のパーサーと独自の仮想マシンをPythonで記述する必要があります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow