[英]How do I get the return value when using Python exec on the code object of a function?
出於測試目的,我想直接執行在另一個 function 內部定義的 function。
我可以通過父 function 的代碼(func_code)獲取子 function 的代碼 object,但是當我執行它時,我沒有返回值。
有沒有辦法從執行代碼中獲取返回值?
是的,您需要在exec
語句中進行賦值:
>>> def foo():
... return 5
...
>>> exec("a = foo()")
>>> a
5
這可能與您的情況無關,因為它用於受控測試,但在使用exec
和用戶定義的輸入時要小心。
幾年后,但以下片段幫助了我:
the_code = '''
a = 1
b = 2
return_me = a + b
'''
loc = {}
exec(the_code, globals(), loc)
return_workaround = loc['return_me']
print(return_workaround) # 3
exec()
本身不返回任何內容,但您可以傳遞一個dict
,其中在執行后存儲了所有局部變量。 通過訪問它,您可以獲得類似回報的東西。
我希望它可以幫助某人。
雖然這是人類見過的最丑陋的野獸,但您可以通過在 exec 調用中使用全局變量來做到這一點:
def my_exec(code):
exec('global i; i = %s' % code)
global i
return i
這是濫用全局變量來跨越邊界獲取數據。
>>> my_exec('1 + 2')
3
毋庸置疑,您永遠不應該允許任何用戶輸入用於此功能的輸入,因為它會帶來極大的安全風險。
這樣的事情可以工作:
def outer():
def inner(i):
return i + 10
for f in outer.func_code.co_consts:
if getattr(f, 'co_name', None) == 'inner':
inner = type(outer)(f, globals())
# can also use `types` module for readability:
# inner = types.FunctionType(f, globals())
print inner(42) # 52
這個想法是從內部函數中提取代碼對象並基於它創建一個新函數。
當內部函數可以包含自由變量時,需要額外的工作。 您還必須提取它們並傳遞給最后一個參數( closure
)中的函數構造函數。
這是一種從 exec 代碼返回值的方法:
def exec_and_return(expression):
exec(f"""locals()['temp'] = {expression}""")
return locals()['temp']
我建議你舉一個你試圖解決的問題的例子。 因為我只會把它作為最后的手段。
這不會得到每個說的返回值,但是在調用exec
以檢索代碼中定義的任何變量時,您可以提供一個空字典。
# Python 3
ex_locals = {}
exec("a = 'Hello world!'", None, ex_locals)
print(ex_locals['a'])
# Output: Hello world!
默認 locals 的行為如下面的函數
locals()
所述:不應嘗試修改默認 locals 字典。 如果您需要在函數exec()
返回后查看代碼對局部變量的影響,請傳遞一個顯式局部變量字典。
有關更多信息,請參閱exec 如何與本地人一起工作?
這是一個帶有簡單代碼的解決方案:
# -*- coding: utf-8 -*-
import math
x = [0]
exec("x[0] = 3*2")
print(x[0]) # 6
從 Python 3.7 開始,字典是有序的。 因此,您不再需要就名稱達成一致,您只需說“最后創建的項目”:
>>> d = {}
>>> exec("def addone(i): return i + 1", d, d)
>>> list(d)
['__builtins__', 'addone']
>>> thefunction = d[list(d)[-1]]
>>> thefunction
<function addone at 0x7fd03123fe50>
使用eval()
而不是exec()
,它返回結果
如果我們需要一個位於另一個目錄中的文件中的函數,例如
我們需要在文件my_py_file.py期函數
位於/home/.../another_directory
我們可以使用以下代碼:
def cl_import_function(a_func,py_file,in_Dir):
... 導入系統
... sys.path.insert(0, in_Dir)
... ax='from %s import %s'%(py_file,a_func)
... loc={}
... exec(ax, globals(), loc)
... getFx = loc[afunc]
...返回getFx
test = cl_import_function('function1',r'my_py_file',r'/home/.../another_directory/')
測試()
(新手的簡單方法...)
program = 'a = 5\nb=10\nprint("Sum =", a + b)'
program = exec(program)
print(program)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.