【发布时间】:2017-05-02 16:21:36
【问题描述】:
我为我的用户提供了一个定义自定义函数 f 的机会,它的
执行取决于他们选择的各种自定义参数parms。
- 他们有责任确保他们需要的每个参数都是 为要评估的函数定义。
- 我有责任运行这个函数。
一个讨厌的解决方案是让他们将自定义代码编写为字符串,然后 用他们需要的参数替换他们的变量名,比如:
## User side
parms = {'a': 5,
'b': 89,
'c': 'third_user_parameter'}
f=\
"""# any operation, user is free:
if len(c) > 10:
result = sum(ord(char) for char in c)
else:
result = a + b
"""
## My side
exec(f, parms, parms)
result = parms['result']
print(result)
这种方法的主要问题(除了result 必须是
作为关键字保留)是用户必须在字符串中定义她的过程,这
很不方便。
有没有一种方法可以让用户定义一个实际的 function 然后使用
是吗?
我怎么能用他们的参数作为变量来评估他们的功能呢?
我需要吗?
简而言之,我希望这可以工作,但事实并非如此:
## User side
parms = {'a': 5,
'b': 89,
'c': 'third_user_parameter'}
def f():
if len(c) > 10:
return sum(ord(char) for char in c)
else:
return a + b
## My side
eval('f()', parms, parms) # NameError: name 'f' is not defined
parms.update({'f': f})
eval('f()', parms, parms) # NameError: name 'c' is not defined
exec('f()', parms, parms) # NameError: name 'c' is not defined
在不改变用户端的情况下,有没有办法我可以在
parms 的“上下文”并得到预期的结果?
【问题讨论】:
-
f.__globals__.update(parms)并将其称为f()(不需要eval)。 -
就是这样。太好了,谢谢:) 这不值得回答吗?
-
坦率地说,这不是一个很好的解决方案,因为它会更新定义函数的模块的全局命名空间。我确信有更好的解决方案
-
如果您可以让您的用户编写函数,使其接受参数作为函数签名中的形式参数,那就更好了。如果他们在正常的 Python 环境中使用相同的函数,则依赖于一些神奇的绑定注入真的很难看。
-
@vaultah 我明白了。我有责任确保用户定义的参数不会覆盖任何重要的东西,但肯定很难控制一切。有没有一种简洁的方式来保护模块标识符?
标签: python python-3.x exec eval evaluation