Python 转义任意代码块
我的脚本接受任意长度和内容的Python代码字符串,然后在exec()语句中运行它们。如果运行任意代码的时间超过了某个预定的限制,则需要退出exec()语句,并且需要设置一个布尔标志以指示过早退出 如何做到这一点 补充资料 这些代码片段将在多个线程中并行运行(或者至少与GIL一样并行) 如果有另一种语言的替代方法,我愿意尝试一下 我计划清理代码,以防止访问任何可能意外损坏系统的内容(文件和系统访问、导入语句、对exec()或eval()的嵌套调用等) 我考虑过的选择Python 转义任意代码块,python,python-3.x,Python,Python 3.x,我的脚本接受任意长度和内容的Python代码字符串,然后在exec()语句中运行它们。如果运行任意代码的时间超过了某个预定的限制,则需要退出exec()语句,并且需要设置一个布尔标志以指示过早退出 如何做到这一点 补充资料 这些代码片段将在多个线程中并行运行(或者至少与GIL一样并行) 如果有另一种语言的替代方法,我愿意尝试一下 我计划清理代码,以防止访问任何可能意外损坏系统的内容(文件和系统访问、导入语句、对exec()或eval()的嵌套调用等) 我考虑过的选择 由于exec()语句在线程中
process.terminate()
终止一切。但我是在Windows上运行的,我读到创建进程可能很昂贵。它还使与管理所有这些的代码的通信变得复杂您提到,您对在Windows上使用进程的担心是它们很昂贵。因此,您可以创建自己的流程池(流程列表)。它们都从队列中提取,您向队列提交新任务。如果任何进程超过超时时间,则将其杀死,并在池中用新进程替换它。这样,您就可以将创建新流程的开销限制在它们超时时,而不是为每个任务创建一个新流程。这里有几个不同的选项 首先,从jdi关于使用多处理的建议开始。这可能是因为Windows进程创建的成本不足以打破您的用例 如果这确实是一个问题,我个人会做的是使用虚拟PC,甚至用户模式Linux,在另一个操作系统中运行相同的代码,而在另一个操作系统中创建进程是很便宜的。你也可以从中得到一个免费的沙箱 如果您不想这样做,jdi关于进程池的建议需要做更多的工作,但只要您不需要经常终止进程,就应该可以很好地工作 如果您确实希望所有内容都是线程,那么您可以这样做,只要您可以限制作业的编写方式。如果作业总是可以干净地展开,那么只需引发一个异常,就可以杀死它们。当然,他们也不必捕获您选择提出的特定异常。显然,作为通用解决方案,这两种情况都不现实,但对于您的用例来说,这可能很好。关键是确保您的CodeEvolver从不插入任何手动资源管理语句(如打开和关闭文件);只有声明。(或者,插入open和close,但插入try/finally)这可能是一个好主意,即使您不这样做,因为剥离数百个进程,例如,每个进程都会泄漏尽可能多的文件句柄,直到它们超时或达到文件限制,这将使您的机器缓慢爬行 如果可以进一步限制代码生成器/演化器,那么可以使用某种形式的协作线程(例如,greenlets),这会使事情变得更好
最后,您可以从CPython切换到一个不同的Python实现,该实现可以在一个进程中运行多个解释器实例。我不知道jython或IronPython能否做到这一点。PyPy可以做到这一点,并且有一个受限的环境沙箱,但不幸的是,我认为这两个沙箱和Python3.x支持都还没有准备好用于黄金时段特性,这意味着您要么必须获得PyPy的特殊构建(可能没有JIT优化器),要么自己构建。这可能是最好的长期解决方案,但它可能不是您今天想要的。我建议在几乎没有权限的用户帐户下运行代码——只有运行代码的权限。由于您正在执行自进化代码,因此对于“任意”的特定定义,它只是“任意”的。这意味着您可能会完全放弃
exec()
,例如将代码包装到函数中exec()
确实允许您在某种程度上隔离代码,但在流程中可以获得更好的隔离。我同意,对您来说最好的解决方案可能是一个流程池,如果流程太长,流程管理器会终止流程。谢谢您的回答。我想到的是一个进程池。但是在您创建流程池之前,请确保它对于您的用例来说确实太昂贵了。最终,您能获得多大的收益取决于您创建了多少流程,以及您必须多长时间完成一次