我遇到了一些相关的答案,但不是我想要的。
这是我现在的代码:
code_str = """
print "this is my global x = " + x
print "And another line is done"
"""
x = 'mystery'
func_template = lambda p: None
func_template.__code__ = compile(code_str, '<string>', 'exec')
func_template() # this executes fine and also has access to x, which i do need.
# func_template('param') # This raises: TypeError: <module>() takes no arguments (1 given)
一些背景; code_str 将来自数据库,我需要在字典中存储大量函数,以便我可以按名称调用任何函数,如下所示:
all_funcs = {}
# Assuming db_result returns a list of name, code tuples from the databse
for name, code in db_result:
all_funcs[name] = my_compile(code)
如果我知道名称,我想用我想要的参数调用所需的函数:
result = all_funcs[by_name](arg1, arg2)
编辑:数据库是可信的,所以我不需要清理或担心恶意代码。
最佳答案
如果替换 lambda 的 __code__
对象,基本上就是重新定义了函数。新的 argcount 由 __code__.co_argcount
决定,因此 lambda 之前接受了哪个或多少个参数并不重要。
如果你想将一个参数传递给编译后的代码,你可以尝试直接eval
你的代码对象,在locals
字典中传递你的参数:
code_str = """
print "this is my global x = " + x
print "And another line is done"
print param
"""
compiled = compile(code_str, "<string>", "exec")
func_template = lambda p=None: eval(compiled, globals(), {'param': p})
x = "1"
func_template()
func_template("2")
这样你显然只能传递关键字参数,不可能使用位置参数。你也可以使用
func_template = lambda **kwargs: eval(compiled, globals(), **kwargs)
将给定的关键字参数直接传递给您的函数。
如果您需要函数的返回值,那么您需要在 'eval'
模式下编译代码,这意味着您必须将代码限制为表达式并且可以'没有声明。
关于来自字符串的 Python 动态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16537857/