Python:有一个用户定义的函数作为输入,同时保持源代码不可访问?

2024-05-29 03:21:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要编写一个以用户定义函数(用python编写)作为输入的软件。在

用户定义函数接受一个数字向量并返回一个数字向量。 我的软件会多次调用这个用户函数(与根搜索相同),然后返回一些结果。在

我的软盘源代码将用Python(它将使用*.pyd)或C++编写,必须隐藏在用户中。在

实现这一目标的最佳方法是什么(如果有的话)?理想情况下,我的python代码是用*.exe编译的,用户可以将自己的函数复制粘贴到一个文本框中,但是从python解释器中使用它也应该是可以接受的。在


Tags: 方法函数代码用户目标软件定义源代码
1条回答
网友
1楼 · 发布于 2024-05-29 03:21:51

这是一个非常有限的例子,它展示了你如何做到这一点当然,这里有一些限制,这只在用户只输入一个函数的情况下有效。如果他们写的字符串看起来更像:

a='garbage'
def foo():pass

甚至:

^{pr2}$

那你就倒霉了。(换句话说,这假设用户只向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.  

请注意,使用python3的exec或python2的execfile可以更安全地完成此操作,其中可以通过将dictionary {'__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(...):和{},如果他们知道python应该是完全直观的。在

ss="""
def foo(x):
    return 5+x
"""

a=5
func=run_user(ss)
result=func(a)     #result = 10

这还有一个优点,即不需要每次调用函数时都重新解析字符串。一旦你有了func,你可以随时使用它。还要注意,在我的解决方案中,您甚至不需要知道用户定义的函数的名称。一旦有了函数对象,名称就不相关了。在

相关问题 更多 >

    热门问题