转义任意代码块

时间:2012-06-29 23:07:56

标签: python python-3.x

我的脚本接受任意长度和内容的Python代码字符串,然后在exec()语句中运行它们。如果运行任意代码的时间超过某个预定限制,那么exec()语句需要退出并且需要设置一个布尔标志来指示过早退出。

如何实现这一目标?

其他信息

这些代码段将在多个线程中并行运行(或者至少与GIL一样平行)。

如果有另一种语言的替代方法,我愿意尝试。

我打算清理代码以防止访问可能会意外损坏我的系统的任何内容(文件和系统访问,import语句,嵌入式调用exec()或eval()等)。

我考虑的选项

  1. 由于exec()语句在线程中运行,因此使用毒丸来杀死线程。不幸的是,我读过毒药并不适用于所有病例。
  2. 在进程内运行exec()语句,然后使用process.terminate()来终止所有内容。但是我在Windows上运行,我读过创建进程可能很昂贵。它还使与管理所有这些的代码的通信变得复杂。
  3. 只允许exec()语句中的预写函数,并让这些函数定期检查退出标志,然后根据需要执行清理。这是复杂,耗时的,并且需要考虑太多的角落案例;我正在寻找一个更简单的解决方案。
  4. 我知道这是一个奇怪的问题值得一个“为什么你会想让任意代码在exec()语句中运行?”回应的类型。我正在尝试一些自我演化的代码。这是我目前的主要绊脚石:如果你允许你的代码几乎做任何事情,那么它可能会永远挂起。你怎么重新获得控制权并在它停止时停止它?

2 个答案:

答案 0 :(得分:3)

这不是一个非常详细的答案,但它比我想要发表评论更多。

您可能需要考虑像creating functions with timeouts, using multiprocessing这样的其他问题作为开始。

线程的问题在于你可能无法使用 poison pill 方法,因为他们不是工作人员需要执行许多小任务。他们会坐在那里阻止发表声明。它永远不会得到退出的价值。

您提到您在Windows上使用进程的担忧是它们很昂贵。所以你可能会做的是创建自己的进程池(进程列表)。他们都从队列中拉出来,然后将新任务提交到队列中。如果任何进程超过超时,则将其终止,并使用新的进程替换它。这样就可以将创建新流程的开销限制在超时时,而不是为每个任务创建一个新流程。

答案 1 :(得分:3)

这里有几个不同的选择。

首先,从jdi建议使用多处理开始。可能是Windows进程创建实际上并不足以破坏您的用例。

如果它确实存在问题,我个人所做的就是使用Virtual PC,甚至是用户模式Linux,在另一个操作系统中运行相同的代码,在这个操作系统中进程创建很便宜。你也可以获得一个免费的沙箱。

如果您不想这样做,jdi对进程池的建议会更多一些工作,但只要您不必经常杀死进程就应该运行良好。

如果您确实希望所有内容都成为线程,那么只要您可以限制写入作业的方式,就可以这样做。如果作业总是可以彻底解开,你可以通过提出异常来杀死它们。当然,他们也不得不抓住你选择提出的具体例外。显然,这些条件都不是现实的解决方案,但对于您的用例,它可能没问题。关键是要确保你的代码evolver永远不会插入任何手动资源管理语句(比如打开和关闭文件);只有声明。 (或者,插入打开和关闭,但在try / finally中。)即使你没有这样做,这也许是一个好主意,因为关闭了数百个进程,例如,每个泄漏的文件句柄都很多因为他们可以在超时或达到文件限制之前将你的机器放慢速度。

如果你可以进一步限制代码生成器/进化器,你可以使用某种形式的协作线程(例如,greenlets),这样可以使事情变得更好。

最后,您可以从CPython切换到可以在单个进程中运行多个解释器实例的不同Python实现。我不知道jython或IronPython是否可以这样做。 PyPy可以做到这一点,并且还有一个受限制的环境沙箱,但遗憾的是我认为这两个 - 以及Python 3.x支持 - 都不是准备好的黄金时段功能,这意味着你要么必须得到一个特殊的构建PyPy(可能没有JIT优化器),或者自己构建它。这可能是最好的长期解决方案,但它可能不是你今天想要的。

相关问题