Python:将用户定义的函数作为输入,同时保持源代码不可访问
Python: have a user-defined function as an input while keeping the source-code inaccessible?
我需要编写一个软件,它将用户定义的函数(用python编写)作为输入。
用户定义的函数采用数字向量并返回数字向量。我的软件会多次调用此用户函数(与根搜索相同的方式),然后返回一些结果。
我的软件的源代码将用python编写(它将使用*.pyd)或C++编写,并且必须对用户隐藏。
实现这一目标的最佳方法(如果有的话)是什么?理想情况下,我会用 *.exe 编译我的 python 代码,用户会将他/她的函数复制粘贴到文本框中,但从 python 解释器使用它也应该是可以接受的。
这是一个非常有限的例子,展示了你如何做到这一点——当然,这里有一些限制——主要是,这只有在用户只输入一个函数时才有效。 如果他们编写的字符串看起来更像:
a='garbage'
def foo():pass
甚至:
def bar():
return foobar()
def foobar():
return "foobar is a cool word, don't you think?"
那你就不走运了。(换句话说,这假设用户只向run_user函数的命名空间添加一件事)。 当然,您可以检查并引发异常或任何结果,如果事实证明用户添加太多......您也可以返回该函数并按照 gauden 的建议使用它。
def run_user(S):
#S is the user's function as a string.
lvars=None #make sure the name is in locals()
lvars=set(locals())
exec(S) #exec isn't usually a good idea -- but I guess you're a very trusting person.
usr_namespace=list(set(locals())-lvars)
usr_func_name=usr_namespace[0]
if(len(usr_namespace)>1):
raise ValueError("User input too much into the namespace!")
usr_func=locals()[usr_func_name]
usr_func() #comment this out if you don't want to run the function immediately
return usr_func
usr_string="""
def foo():
a="Blah"
print "Hello World! "+a
"""
func_handle=run_user(usr_string) #prints "Hello World! Blah"
#and to demonstrate that we can pass a handle to the function around:...
func_handle() #prints "Hello World! Blah" again.
请注意,您可以使用python 3的exec
或python 2的execfile
更安全地执行此操作,您可以通过将字典{'__builtins__':None}
作为全局字典传递来限制用户函数的命名空间
#python3.x
allowed=vars(__builtins__).copy()
allowed['__import__']=None
exec("import os",{'__builtins__':None},allowed) #raises ImportError
exec("print(abs(-4))",{'__builtins__':None},allowed) #prints 4 as you'd expect.
我希望同样的事情适用于 python2.x 下的execfile
,前提是您将字符串写入临时文件......
编辑(以解决下面的评论)
您提供的示例可以更简单地完成eval
:
a=5
b=eval('a+5') #b == 10
但是,这不是您所要求的。 你要求的是用户可以编写一个函数,例如:
def f(a):
return a+5
前一种情况将起作用,但用户需要知道变量名称为"a"。
a=5
b=eval('x+5') #won't work -- x isn't defined
他们还需要知道如何添加向量 - (如果你使用的是numpy数组,那是微不足道的,但我想我会提到它以防万一你不是)。 而且,他们不能在没有大量工作和挠头的情况下制作复杂的表达式(使用多个条件、循环等的长表达式)。
后一种情况更好一些(在我看来),因为它更通用。 您可以使用我描述的方法获取函数(删除我实际运行函数的部分),并且用户可以使用他们想要的任何变量名称 - 然后您只需使用他们的函数。 它们还可以执行循环之类的操作,并使用比您在带有 eval
的单行中执行的表达式复杂得多的表达式。 您为此付出的唯一代价是,用户需要在最后编写def func(...):
和return some_value
,如果他们知道python应该是完全直观的。
ss="""
def foo(x):
return 5+x
"""
a=5
func=run_user(ss)
result=func(a) #result = 10
这也有一个优点,即每次要调用函数时都不需要重新解析字符串。 一旦你有了func
,你可以随时随地使用它。 另请注意,使用我的解决方案,您甚至不需要知道用户定义的函数的名称。 拥有函数对象后,名称就无关紧要了。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 在Linux中哪里可以找到互斥、未来等的源代码
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 从C++dll访问C#中的一行主要参数
- 概念TS检查忽略私有访问修饰符
- 访问被拒绝后,c++中的故障保护代码
- 在c++中访问int到类对象的映射时出错
- 我想访问std::unique_ptr中的一个特定元素
- GDB 7.5 (OS X):无法从库函数访问源代码
- Python:将用户定义的函数作为输入,同时保持源代码不可访问
- 在事件DownloadComplete上访问HTML源代码