在运行时使用用户提供的python代码

时间:2011-08-02 18:26:25

标签: python exec eval

我正在开发一个对来自数据库的(任意)数据进行操作的系统。在系统可以使用之前,数据可能需要一些预处理。为了允许用户指定可能复杂的规则,我允许用户输入用于执行此任务的Python代码。该系统是纯Python。

我的计划是将表和列作为变量引入,并让用户使用Python可以执行的任何操作(包括访问标准库)。现在我的问题:

如何获取字符串(用户输入),将其编译为Python(添加代码以提供输入数据后)并获取输出。我认为最简单的方法是将用户输入的数据用作方法的主体,并将该函数的返回值作为我的新数据。

这可能吗?如果有,怎么样?用户可能输入恶意代码并不重要,因为可能发生的最糟糕的事情是,他搞砸了自己的系统,幸好这不是我的问题;)

6 个答案:

答案 0 :(得分:4)

Python提供了一个exec()语句,它可以做你想要的。您将希望传递您想要的变量作为函数的第二个和/或第三个参数(分别为全局变量和局部变量),因为它们控制运行exec的环境。

例如:

env = {'somevar': 'somevalue'}
exec(code, env)

或者,如果您要执行的代码存储在自己的文件中,execfile()可以以类似的方式使用。

如果您只有一个要执行的表达式,也可以使用eval

答案 1 :(得分:2)

  

这可能吗?

如果它不涉及时间旅行,反重力或永久运动,这个问题的答案总是“是”。你不需要问这个。

正确的进行方式如下。

您使用一些方便的库和包构建框架。

您构建了一些实现此要求的示例应用程序:“在系统可以使用之前,数据可能需要一些预处理。”

您编写有关该应用程序如何导入和使用框架中的模块的文档。

您将框架,示例应用程序和文档转交给用户,让他们构建这些应用程序。

不要浪费时间“取一个字符串(用户输入),将其编译为Python(添加代码以提供输入数据后)并获取输出”。

用户应该编写这样的应用程序。

from your_framework import the_file_loop
def their_function( one_line_as_dict ):
    one_line_as_dict['field']= some stuff
the_file_loop( their_function )

这实际上可能是整个计划。

你必须写the_file_loop,看起来像这样。

def the_file_loop( some_function ):
    with open('input') as source:
        with open('output') as target:
            for some_line in source:
                the_data = make_a_dictionary( some_line )
                some_function( the_data )
                target.write( make_a_line( the_data ) )

通过创建框架,并允许用户编写自己的程序,您将对结果更加满意。不那么神奇。

答案 2 :(得分:1)

2个选择:

  • 您接受他的输入并将其放入文件中,然后执行它。
  • 您使用exec()

答案 3 :(得分:0)

如果您只想设置一些本地值然后提供python shell,请查看code module

您可以启动一个类似于python shell的shell实例,并使用您想要的任何局部变量对其进行初始化。这将假设您想要使用结果值的任何功能都内置在您作为本地传入的类中。

示例:

shell = code.InteractiveConsole({'foo': myVar1, 'bar': myVar2})

答案 4 :(得分:0)

您真正想要的是exec,因为eval仅限于获取表达式并返回值。使用exec,您可以拥有代码块(语句)并处理任意复杂的数据,作为代码的全局和局部传入。

然后代码通过某些约定返回结果(比如将其绑定到result)。

答案 5 :(得分:-1)

嗯,您正在描述compile()

但是......我想我仍然会使用常规的python源文件来实现它。在路径中添加一个特殊位置,比如'〜/ .myapp / plugins',然后只有__import__所有内容。您可能希望提供一些方便的基类来公开您尝试提供的界面,以便您的用户可以继承它们。