簡體   English   中英

如何在 Python 中執行包含 Python 代碼的字符串?

[英]How do I execute a string containing Python code in Python?

如何在 Python 中執行包含 Python 代碼的字符串?

對於語句,使用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

但是,第一步應該是問問自己是否真的需要。 執行代碼一般應該是最后的position:如果它可以包含用戶輸入的代碼,它會很慢、很丑而且很危險。 您應該始終首先查看替代方案,例如高階函數,看看它們是否能更好地滿足您的需求。

在示例中,使用 exec function 將字符串作為代碼執行。

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()

evalexec是正確的解決方案,它們可以以更安全的方式使用。

正如Python 參考手冊中討論的和教程中明確解釋的那樣, evalexec函數采用兩個額外的參數,允許用戶指定可用的全局和局部函數和變量。

例如:

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

本質上,您正在定義將在其中執行代碼的命名空間。

請記住,從版本 3 開始, exec是一個函數!
所以總是使用exec(mystring)而不是exec mystring

避免execeval

在 Python 中使用execeval是非常不受歡迎的。

有更好的選擇

從最佳答案(強調我的):

對於語句,請使用exec

當您需要表達式的值時,請使用eval

但是,第一步應該是問問自己是否真的需要。 執行代碼通常應該是最后手段的 position :如果它可以包含用戶輸入的代碼,它會很慢、很丑而且很危險。 您應該始終首先查看替代方案,例如高階函數,看看它們是否能更好地滿足您的需求。

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() 的嘗試的問題在於它們是黑名單 他們明確地刪除了可能是危險的東西。 這是一場失敗的戰斗,因為如果列表中只剩下一個項目,您就可以攻擊系統

那么,可以使 eval 安全嗎? 很難說。 在這一點上,我最好的猜測是,如果你不能使用任何雙下划線,你就不會造成任何傷害,所以如果你排除任何帶有雙下划線的字符串,你是安全的。 也許...

很難閱讀和理解

來自http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (強調我的):

首先, exec使人類更難閱讀您的代碼 為了弄清楚發生了什么,我不僅要閱讀你的代碼,我還必須閱讀你的代碼,弄清楚它將生成什么字符串,然后閱讀那個虛擬代碼。 所以,如果你在一個團隊中工作,或者發布開源軟件,或者在 StackOverflow 之類的地方尋求幫助,你會讓其他人更難幫助你。 而且,如果您有任何機會在 6 個月后調試或擴展此代碼,那么您將直接讓自己變得更加困難。

eval()僅用於表達式,而eval('x+1')有效, eval('x=1')例如不起作用。 在這種情況下,最好使用exec ,甚至更好:嘗試找到更好的解決方案:)

您可以使用 exec 完成代碼的執行,如以下 IDLE session:

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

4

值得一提的是,如果要調用 python 文件,則存在exec的兄弟也稱為execfile 如果您在包含糟糕 IDE 的第三方 package 中工作,並且您想在其 package 之外進行編碼,這有時會很好。

例子:

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

或者:

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

正如其他人提到的,它是“執行”..

但是,如果您的代碼包含變量,您可以使用“全局”來訪問它,也可以防止編譯器引發以下錯誤:

NameError:名稱“p_variable”未定義

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

使用eval

查看eval

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

我嘗試了很多東西,但唯一有效的是以下內容:

temp_dict = {}
exec("temp_dict['val'] = 10") 
print(temp_dict['val'])

output:

10

好的..我知道這不完全是一個答案,但可能是給像我一樣看這個的人的注釋。 我想為不同的用戶/客戶執行特定的代碼,但也想避免 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

最合乎邏輯的解決方案是使用內置的eval() function。另一種解決方案是將該字符串寫入臨時 python 文件並執行它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM