将动态生成的代码存储为字符串或代码对象?

时间:2009-08-18 10:10:42

标签: python exec

我正在攻击一个小模板引擎。我有一个类(夸张地命名为模板编译器),它产生一串动态生成的代码。

例如:

def dynamic_function(arg):
  #statement
  return rendered_template

在渲染时,我用这个代码调用内置函数 exec ,使用自定义全局字典(为了尽可能地控制插入的代码)由潜在的恶意用户进入模板。)

但是,我需要缓存已编译的模板以避免在每次执行时编译它。我想知道最好将字符串存储为纯文本并每次加载它或使用编译来生成code_object并存储该对象(例如使用shelve模块)。

也许值得一提的是,最终我想让我的模板引擎线程安全。

感谢阅读! 托马斯

编辑:因为S.Lott更好地强调本身没有意义。我的意思是更快更快,消耗更少的内存更简单,更容易调试。当然,更多更美味的免费咖啡会更好。

3 个答案:

答案 0 :(得分:2)

您没有提到要存储这些模板的位置,但如果您要“永久”地保存它们,请记住Python不保证跨主要版本的字节码兼容性。因此要么选择一个确保兼容性的方法(比如存储源代码),要么在编译模板旁边存储足够的信息,以便在编译模板无效时将其丢弃。

marshal模块也是如此:例如:使用Python 2.5编组的值不允许用Python 2.6读取。

答案 1 :(得分:1)

就个人而言,我会存储文字。您可以使用编辑器或其他任何内容查看文本,这将使调试和混乱变得更容易。如果要测试缓存文件的内容是否符合预期,那么编写单元测试也要容易得多。

稍后,如果你发现你的系统不够快,如果分析显示解析缓存的模板需要花费很多时间,你可以尝试切换到存储字节码 - 但仅限于此。只要存储机制被正确封装,这种改变应该是相当轻松的。

答案 2 :(得分:0)

Mako模板库将编译后的模板缓存为python模块,并使用内置的imp模块来处理字节码缓存和代码加载。这对于解释器中的更改似乎相当健壮,快速且易于调试(您可以在缓存中查看生成的代码的来源)。

请参阅mako.template模块了解其处理方法。