【问题标题】:Calling user-defined function as native | Python以原生方式调用用户自定义函数 | Python
【发布时间】:2012-08-26 19:19:56
【问题描述】:

我正在构建一个类似于 Mathwork 的 Simulink 或 Tanner-Spice 的系统,其中用户使用可用的运算符定义函数。然后我需要运行该函数并将响应返回给用户。我正在使用 Javascript 进行 UI 交互。在内部,用户定义函数 (UDF) 被捕获为 JSON 并传递到解析此 JSON 的 Python 服务器。

我的问题是,我现在如何运行这个 UDF?我不担心恶意用户利用这种能力进行黑客攻击,因为我所有的用户都是受信任的。

我认为的一种方法是将 UDF 作为 python 脚本写入磁盘,然后运行 ​​commands.getstatusoutput()。这里的问题是该函数可能需要多个输入,而无法传递这些。

我正在寻找的是能够动态加载新的 python 文件及其函数,并能够调用它们。


找到了一篇解释如何执行此操作的博客文章。我想问题是我没有使用正确的关键字进行搜索。

无论如何,David Janes 的博客 here 解释了如何动态加载 python 脚本。

如果有更好的方法来做我想做的事,我仍然会邀请你们发表评论并提出建议。

谢谢, 尼克

【问题讨论】:

  • UDF 是 Python 可调用的吗?如果是这样,您可以像在this answer 中那样编组/腌制它。
  • 感谢您的评论@ezod。我从未使用过 marshal/pickle,基本文档看起来有点复杂。它在我的情况下可能有用,但我必须深入细节来验证它。
  • 即使您信任您的用户,但这并不意味着您可以信任输入。如果这样做,您将让它们和您的网站对CSRF 漏洞利用等开放。

标签: python dynamic load user-defined-functions


【解决方案1】:

这是一个简单的类,它可以从代码字符串、文件或代码对象中创建类似模块的对象:

class DynamicModule(object):
    def __init__(self, code):
        exec code in self.__dict__

示例用法:

>>> mod = DynamicModule("""
... def foo(x, y):
...     print x**2 + y
... """)
>>> 
>>> mod.foo(10, 20)

文件示例(假设/tmp/hello.py 包含一个名为hello 的函数):

>>> mod2 = DynamicModule(open('/tmp/hello.py'))
>>> mod2.hello('World')
Hello, World!

【讨论】:

    【解决方案2】:

    您可以为此使用exec 模块,因为输入是可信的。

    exec 文档:http://docs.python.org/reference/simple_stmts.html#exec

    文档摘录:

    This statement supports dynamic execution of Python code. The first expression should evaluate to either a string, an open file object, or a code object. If it is a string, the string is parsed as a suite of Python statements which is then executed (unless a syntax error occurs). [1] If it is an open file, the file is parsed until EOF and executed. If it is a code object, it is simply executed. In all cases, the code that’s executed is expected to be valid as file input (see section File input).

    但是,您应该注意,在使用 exec 时,您不能在函数之外使用 returnyield 语句。

    例子:

    your_json_data="def example(arg1,arg2):    print arg1,arg2"
    exec(your_json_data)
    example("Hello","World")
    ##Output: "Hello World"
    

    【讨论】:

    • 感谢您指出exec。尽管就我而言,这可能行不通。我正在运行一个服务器(比如 myserver)。它有一个特定的数据结构(比如一个数组),它想要传递给一个保存在 python 文件(比如udfile.py)中的 UDF(比如userfunc())。我希望能够致电userfunc(array)exec 让我只运行 udfile.py 而不是加载 它作为一个模块并使用参数调用userfunc。如果我错了,请纠正我。
    • 您必须将其保存为文件吗?您可以直接从json 数据中获取exec 数据,并且可以像使用模块一样使用它。我将在我的答案中添加一个示例。
    【解决方案3】:

    要导入sys.path 中具有固定名称的 Python 文件:

    import mod # it can import mod.py file
    
    result = mod.some_function(*args)
    

    如果模块名称在字符串中,则导入模块:

    import importlib
    
    m = importlib.import_module("mod")
    result = m.some_function(*args)
    

    如果模块的内容包含在字符串中:

    ns = {}
    exec """
    
    def some_function(a, b):
        return a + b
    
    # other functions, classes or any code
    """ in ns
    
    result = ns['some_function'](1, 2)
    print result # -> 3
    

    如果您不能完全控制输入,那么您应该在受限环境中执行上述代码,例如,您可以将字符串发送到a sandboxed pypy interpreter

    Python 可以解析 Python

    ast module可以帮助您以安全的方式解析和操作代码,例如:Evaluating a mathematical expression in a string

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多