【问题标题】:Safely using eval to calculate using the math module in python使用 python 中的数学模块安全地使用 eval 进行计算
【发布时间】:2020-10-31 03:14:04
【问题描述】:

我想从用户输入的字符串中获取计算结果,同时使用sinceilmath 函数。我也希望能够以sin(30) 而非math.sin(30) 的身份进行操作。我以为做

from math import *

会起作用,因为当我全部导入时,它会显示为内置函数,并且会导入内置函数。但是,当我运行代码时,它显示数学函数在 eval() 中不起作用

>>> from math import *
>>> sin
<built-in function sin>
>>> print
<built-in function print>
>>> eval("sin(30)", {}, {})
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    eval("sin(30)", {}, {})
  File "<string>", line 1, in <module>
NameError: name 'sin' is not defined

我是否必须手动添加所有数学函数,或者有更简单的方法吗?

【问题讨论】:

  • 您使用空的本地和全局命名空间显式运行 eval
  • 除了上述之外,没有什么比任何其他使用 eval 更安全的了。不确定标题中的safely 指的是什么。
  • "当我全部导入时,它显示为内置函数,并且内置函数被导入" - "内置函数 sin" 中的 "built-in" 表示它是用C. 这与它是否在内置命名空间中可用完全无关。不幸的是,“内置”在 Python 中意味着多个不相关的东西。 (此外,使内置名称自动可用的机制与导入无关。)
  • 即使命名空间为空,恶意代码也可以执行().__class__.__base__.__subclasses__()[-1].__init__.__globals__['__builtins__']['__import__']('os').system('install ransomware or something') 之类的操作来运行任意shell 命令并做出可怕的事情。 eval 根本上是错误的工具。这很方便,但是错了。
  • @tdelaney:如果__builtins__ 不存在于提供的全局变量中,eval 会为评估代码提供默认内置函数。但是,即使您明确将代码设为空 __builtins__,我的评论之类的内容仍然有效,因为它甚至不依赖于可用的内置名称。

标签: python eval


【解决方案1】:

关于“安全”,这取决于您的意思。您可以很容易地提供对全局环境的访问,从而使表达式可以访问您导入的任何内容。但是没有什么可以阻止用户输入一个可以做意想不到的事情的表达式,所以如果这个表达式来自一个不受信任的用户,那么你应该避免使用eval

话虽如此,您可以使您的示例按如下方式工作:

>>> from math import *
>>> eval("sin(30)", globals())
-0.9880316240928618
>>> 

请注意,在此示例中,30 被解释为弧度而不是度数。

【讨论】:

    【解决方案2】:
    $ echo -e  'import math\nmathok={k: v for k, v in math.__dict__.items() if not k.startswith("__")}\nprint(eval("3*pi",{"__builtins__": {}},mathok))' | python               
    9.42477796076938
    

    【讨论】:

    • 至于此页面上的所有其他答案和 cmets - OMG - 为什么对某个主题一无所知的人坚持发表他们的错误意见。 python中的eva() 专门设计的,当你正确使用它时是安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2015-02-25
    • 2013-09-23
    相关资源
    最近更新 更多