451

Python コードを含む文字列を Python で実行するにはどうすればよいですか?

4

14 に答える 14

423

ステートメントには、exec(string)(Python 2/3)またはexec string(Python 2)を使用します。

>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world

式の値が必要な場合は、次を使用しますeval(string)

>>> x = eval("2+2")
>>> x
4

ただし、最初のステップは、本当に必要かどうかを自問することです。コードの実行は、通常、最後の手段となるはずです。ユーザーが入力したコードを含めることができる場合、コードは遅く、醜く、危険です。高階関数などの代替案を常に最初に調べて、これらがニーズをより適切に満たすことができるかどうかを確認する必要があります。

于 2009-03-31T16:15:24.567 に答える
82

この例では、文字列はexec関数を使用してコードとして実行されます。

import sys
import StringIO

# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()

code = """
def f(x):
    x = x + 1
    return x

print 'This is my output.'
"""

# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr

exec code

# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

print f(4)

s = codeErr.getvalue()

print "error:\n%s\n" % s

s = codeOut.getvalue()

print "output:\n%s" % s

codeOut.close()
codeErr.close()
于 2009-03-31T16:14:38.343 に答える
34

evalとは正しい解決策であり、より安全なexec方法で使用できます。

Python のリファレンス マニュアルで説明され、このチュートリアルで明確に説明されているように、evalおよびexec関数は、ユーザーが使用可能なグローバル関数とローカル関数および変数を指定できるようにする 2 つの追加パラメーターを取ります。

例えば:

public_variable = 10

private_variable = 2

def public_function():
    return "public information"

def private_function():
    return "super sensitive information"

# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len

>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12

>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined

>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters

>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined

本質的には、コードが実行される名前空間を定義しています。

于 2013-02-17T21:44:32.323 に答える
15

避けexeceval

Python でexecandを使用することは、非常に嫌われています。eval

より良い代替手段があります

一番上の答えから(私の強調):

ステートメントには、 を使用しますexec

式の値が必要な場合は、 を使用しますeval

ただし、最初のステップは、本当に必要かどうかを自問することです。コードの実行は、一般的に最後の手段であるべきです。ユーザーが入力したコードが含まれる可能性がある場合、遅く、醜く、危険です。高階関数などの代替案を常に最初に調べて、これらがニーズをよりよく満たすことができるかどうかを確認する必要があります。

Alternatives から exec/eval へ?

文字列の名前を持つ変数の値を設定および取得する

[while eval] は機能しますが、通常、プログラム自体に意味のある変数名を使用することはお勧めしません。

代わりに、辞書を使用することをお勧めします。

慣用句ではありません

http://lucumr.pocoo.org/2011/2/1/exec-in-python/から(強調は私のもの)

Python は PHP ではありません

他の言語ではやり方が異なるため、Python のイディオムを回避しようとしないでください。名前空間が Python にあるのには理由があります。ツールを提供するからといって、execそのツールを使用する必要があるわけではありません。

危険です

http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.htmlから(私の強調)

そのため、すべてのグローバルとビルトインを削除しても、eval は安全ではありません!

eval() を保護しようとするこれらすべての試みの問題は、それらがブラックリストであるということです。危険な可能性があるものを明示的に削除します。リストからアイテムが 1 つでも残っていれば、システムを攻撃できるため、それは負け戦です。

では、eval を安全にすることはできますか? 言いにくい。この時点で、私の最善の推測では、2 つのアンダースコアを使用できなくても問題はないので、2 つのアンダースコアを含む文字列を除外すれば安全です。多分...

読みにくいし分かりにくい

http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.htmlから(私の強調):

まず、exec人間がコードを読むのが難しくなります。何が起こっているのかを理解するために、私はあなたのコードを読むだけでなく、あなたのコードを読んで、それが生成する文字列を理解し、その仮想コードを読む必要があります。したがって、チームで作業している場合、オープン ソース ソフトウェアを公開している場合、または StackOverflow のような場所で助けを求めている場合は、他の人があなたを助けるのを難しくしています。そして、今から 6 か月後にこのコードをデバッグまたは拡張する可能性がある場合は、直接自分自身を困難にしています。

于 2016-02-29T19:01:54.950 に答える
13

eval()は式のためだけのものですが、eval('x+1')機能eval('x=1')しますが、たとえば機能しません。その場合、 を使用することをお勧めしますexec。または、より良い解決策を見つけてみてください :)

于 2010-11-25T16:03:11.053 に答える
9

次のIDLEセッションのように、execを使用してコードを実行します。

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']

4
于 2012-07-18T22:51:49.133 に答える
5

evalを使用します。

于 2009-03-31T16:13:49.127 に答える
5

evalをチェックアウト:

x = 1
print eval('x+1')
->2
于 2009-03-31T16:14:05.770 に答える
1

最も論理的な解決策は、組み込みのeval()関数を使用することです。別の解決策は、その文字列を一時的なPythonファイルに書き込んで実行することです。

于 2009-03-31T16:15:10.510 に答える