[英]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()
eval
和exec
是正確的解決方案,它們可以以更安全的方式使用。
正如Python 參考手冊中討論的和本教程中明確解釋的那樣, eval
和exec
函數采用兩個額外的參數,允許用戶指定可用的全局和局部函數和變量。
例如:
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
。
exec
和eval
exec
和eval
是非常不受歡迎的。從最佳答案(強調我的):
對於語句,請使用
exec
。當您需要表達式的值時,請使用
eval
。但是,第一步應該是問問自己是否真的需要。 執行代碼通常應該是最后手段的 position :如果它可以包含用戶輸入的代碼,它會很慢、很丑而且很危險。 您應該始終首先查看替代方案,例如高階函數,看看它們是否能更好地滿足您的需求。
使用字符串中的名稱設置和獲取變量的值
[雖然
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.