Python eval在函数中不起作用

时间:2012-07-10 18:20:15

标签: python function eval

我正在使用this代码来评估字符串中的数学表达式。它有效:

#!/usr/bin/env python
from __future__ import division
from math import *

expression = raw_input()

# Math functions
safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

# Create safe directory
safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
safe_dict['abs'] = abs

result = eval(expression, {"__builtins__": None}, safe_dict)
print result

我把它包装在这样的函数中:

#!/usr/bin/env python
from __future__ import division
from math import *

def calculate(expression):
    # Math functions
    safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

    # Create safe directory
    safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
    safe_dict['abs'] = abs

    result = eval(expression, {"__builtins__": None}, safe_dict)
    if isinstance(result, float) and result.is_integer():
        result = int(result)
    print result

expr = raw_input()
calculate(expr)

它仍然适用于基本操作,但safe_dict中定义的所有功能都不起作用。 5**5适用于这两个程序,但是sin(pi)使用了第一个代码示例,但它不适用于第二个代码。回溯是

Traceback (most recent call last):
  File "stack.py", line 20, in <module>
    calculate(expression)
  File "stack.py", line 14, in calculate
    result = eval(expression, {"__builtins__": None}, safe_dict)
  File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not callable

3 个答案:

答案 0 :(得分:6)

它失败的原因是你从数学模块导入的函数不是函数内的局部变量;他们是全球性的。因此,当您读取locals()并插入dict时,它会为每一个插入None。如果您删除get(key, None)并直接访问locals()[key],则会看到此消息。

更好的方法是在数学模块上使用getattr。 import math(不是from math import *),然后执行safe_dict = dict((k, getattr(math, k)) for k in safe_list)

答案 1 :(得分:3)

calculate()函数中,locals()不包含从math导入的函数。因此,safe_dict填充了大量None

您可以在safe_dict之外构建calculate(),如果您多次拨打calculate(),也可以提高效果。

答案 2 :(得分:1)

这可能是因为'math'中有safe_list,而math是一个模块。对我来说,似乎eval正在做math(),这会导致它阻碍它的运作方式。

尝试从'math'移除safe_list,看看是否有帮助。

旁注:我不确定这是做你想做的最好的方法。我认为需要改变设计。