【问题标题】:How do I evaluate Python code from a string quickly?如何快速评估字符串中的 Python 代码?
【发布时间】:2020-02-08 22:22:05
【问题描述】:

我正在编写一个程序,它必须从字符串中执行数百万次 Python 代码。有没有比使用eval() 更快的方法呢?运行eval()中的代码大约需要100微秒,运行嵌入到程序中只需要8微秒。有没有类似eval()的方法执行时间更短?

【问题讨论】:

  • 如果 eval 返回一个“执行工作的函数”(例如 lambda 或其他可调用函数),则结果可以被缓存并再次更快地执行,因为跳过了整个解析阶段:它大约就像调用了现有方法。 (如果总是使用不同的字符串,则不适用:但是,即使在这种情况下,也许可以提取共性?)
  • 你不应该使用eval,而是使用ast.literal_eval
  • @aws_apprentice, ast.literal_eval 绝对更安全,但它并没有像 eval() 那样做。 OP,这是很重要的一点:字符串来自哪里?如果它们来自不受信任的来源,您绝对不应该通过eval() 运行它们。这是一个主要的安全问题。 eval() 的好的用例很少。
  • 然后让 eval 表达式为,例如:“lambda x, y: x ** 2 + y”(或者甚至不使用 eval,尽管这可能是用于图形计算器,其中用户可以输入表达式作为函数:)。然后让 f = eval(expression_returning_lambda);并使用 r = f(x, y),其中 f 只为相同的表达式输入创建一次,并被多次调用..
  • 你能分享更多的上下文吗?根据我们掌握的有限信息,我认为使用eval() 是不合理的。

标签: python string performance eval


【解决方案1】:

我会重组您的代码,使其不必是 evaled(例如,采用函数参数而不是字符串)

如果等式绝对必须来自一个字符串,你可以预先编译它:

In [1]: x = y = 0

In [2]: %timeit eval('x ** 2 + y')
5.95 µs ± 223 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [3]: code = compile('x ** 2 + y', '<string>', 'eval')

In [4]: %timeit eval(code)
608 ns ± 9.88 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

compile 不是让eval 在每次调用时都将字符串编译为字节码,而是事先进行。

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 2017-05-26
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多