web-dev-qa-db-ja.com

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

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

293
hekevintran

例では、文字列は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()
60
hekevintran

ステートメントには、 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

しかし、最初のステップは、本当に必要なのかどうか自分自身に尋ねることです。コードを実行することは、一般的に最後の手段となるべきです。ユーザーが入力したコードが含まれていると、遅くて醜くて危険です。高階関数のような代替手段を常に最初に見て、それらがあなたのニーズをよりよく満たすことができるかどうかを確かめるべきです。

280
Brian

バージョン3からexecは関数です。
したがって、常にexec mystringではなくexec(mystring)を使用してください。

20
bheks

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

Pythonのリファレンスマニュアル で説明され、 this チュートリアルで明確に説明されているように、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

要するに、あなたはコードが実行される名前空間を定義しているのです。

19
alan

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

11
LGB

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

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

4
9
gus

execevalは避けてください

Pythonでexecevalを使用することは非常に嫌です。

より良い選択肢があります

トップの答えから(私の強調点):

文の場合はexecを使用してください。

式の値が必要なときはevalを使用してください。

しかし、最初のステップは、本当に必要なのかどうか自分自身に尋ねることです。 コードを実行することは、一般的に最後の手段になるはずです:ユーザーが入力したコードが含まれていると、遅くて醜くて危険です。あなたは常に高次関数のような最初の選択肢を最初に見て、それらがあなたのニーズをよりよく満たすことができるかどうかを確かめるべきです。

From exec/evalの代わりに?

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

[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つだけアイテムが残っていると、システムを攻撃できるので、これは負けた戦いです。

だから、評価は安全にすることができますか?言いにくい。現時点では、二重下線を使用できない場合は害を及ぼすことはできないと思われるので、二重下線を含む文字列を除外しても安全です。多分...

読みにくく理解しにくい

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

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

9
Caridorc

チェックアウト eval

x = 1
print eval('x+1')
->2
4
ryeguy

eval を使ってください。

3

最も論理的な解決策は組み込みの eval() 関数を使うことです。もう一つの解決策はその文字列を一時的なpythonファイルに書いて実行することです。

3
John T

Pythonファイルを呼び出したい場合は、execname __の兄弟がexecfilename__と同じ名前で存在することを言及する価値があります。ひどいIDEが含まれているサードパーティのパッケージで作業していて、それらのパッケージの外側でコーディングしたいのであれば、それは良いことです。

例:

execfile('/path/to/source.py)'

または:

exec(open("/path/to/source.py").read())

2
user1767754

他の人が言ったように、それは "exec"です..

ただし、コードに変数が含まれている場合は、「global」を使用してそれにアクセスできます。また、コンパイラが次のエラーを発生させないようにすることもできます。

NameError:名前 'p_variable'は定義されていません

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
1
Ghanem

わかりました。私はこれがまさに答えではないことを知っています、しかし私がそうであったようにこれを見ている人々のための多分メモ。私は異なるユーザー/顧客のために特定のコードを実行したいと思いましたが、exec/evalを避けたいと思いました。私は最初に各ユーザーのためにデータベースにコードを保存して、上記をすることに目を向けました。

ファイルシステム上の「customer_filters」フォルダー内にファイルを作成し、「imp」モジュールを使用しました。その顧客にフィルターが適用されていない場合は、そのまま続行しました

import imp


def get_customer_module(customerName='default', name='filter'):
    lm = None
    try:
        module_name = customerName+"_"+name;
        m = imp.find_module(module_name, ['customer_filters'])
        lm = imp.load_module(module_name, m[0], m[1], m[2])
    except:
        ''
        #ignore, if no module is found, 
    return lm

m = get_customer_module(customerName, "filter")
if m is not None:
    m.apply_address_filter(myobj)

したがって、customerName = "jj"はcustomer_filters\jj_filter.pyファイルからapply_address_filterを実行します。

0
Brian