Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 转义任意代码块_Python_Python 3.x - Fatal编程技术网

Python 转义任意代码块

Python 转义任意代码块,python,python-3.x,Python,Python 3.x,我的脚本接受任意长度和内容的Python代码字符串,然后在exec()语句中运行它们。如果运行任意代码的时间超过了某个预定的限制,则需要退出exec()语句,并且需要设置一个布尔标志以指示过早退出 如何做到这一点 补充资料 这些代码片段将在多个线程中并行运行(或者至少与GIL一样并行) 如果有另一种语言的替代方法,我愿意尝试一下 我计划清理代码,以防止访问任何可能意外损坏系统的内容(文件和系统访问、导入语句、对exec()或eval()的嵌套调用等) 我考虑过的选择 由于exec()语句在线程中

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

如何做到这一点

补充资料 这些代码片段将在多个线程中并行运行(或者至少与GIL一样并行)

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

我计划清理代码,以防止访问任何可能意外损坏系统的内容(文件和系统访问、导入语句、对exec()或eval()的嵌套调用等)

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

    这不是一个非常详细的答案,但它比我想在评论中说的要多

    <>你可能想把这个问题当作一个开始来考虑。 线程的问题是,您可能无法使用“毒丸”方法,因为它们不是执行许多小任务的工作者。他们会坐在那里阻止发表声明。它永远不会得到要退出的值


    您提到,您对在Windows上使用进程的担心是它们很昂贵。因此,您可以创建自己的流程池(流程列表)。它们都从队列中提取,您向队列提交新任务。如果任何进程超过超时时间,则将其杀死,并在池中用新进程替换它。这样,您就可以将创建新流程的开销限制在它们超时时,而不是为每个任务创建一个新流程。

    这里有几个不同的选项

    首先,从jdi关于使用多处理的建议开始。这可能是因为Windows进程创建的成本不足以打破您的用例

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

    如果您不想这样做,jdi关于进程池的建议需要做更多的工作,但只要您不需要经常终止进程,就应该可以很好地工作

    如果您确实希望所有内容都是线程,那么您可以这样做,只要您可以限制作业的编写方式。如果作业总是可以干净地展开,那么只需引发一个异常,就可以杀死它们。当然,他们也不必捕获您选择提出的特定异常。显然,作为通用解决方案,这两种情况都不现实,但对于您的用例来说,这可能很好。关键是确保您的CodeEvolver从不插入任何手动资源管理语句(如打开和关闭文件);只有声明。(或者,插入open和close,但插入try/finally)这可能是一个好主意,即使您不这样做,因为剥离数百个进程,例如,每个进程都会泄漏尽可能多的文件句柄,直到它们超时或达到文件限制,这将使您的机器缓慢爬行

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


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

    我建议在几乎没有权限的用户帐户下运行代码——只有运行代码的权限。由于您正在执行自进化代码,因此对于“任意”的特定定义,它只是“任意”的。这意味着您可能会完全放弃
    exec()
    ,例如将代码包装到函数中
    exec()
    确实允许您在某种程度上隔离代码,但在流程中可以获得更好的隔离。我同意,对您来说最好的解决方案可能是一个流程池,如果流程太长,流程管理器会终止流程。谢谢您的回答。我想到的是一个进程池。但是在您创建流程池之前,请确保它对于您的用例来说确实太昂贵了。最终,您能获得多大的收益取决于您创建了多少流程,以及您必须多长时间完成一次