gpt4 book ai didi

python - 在 Python 中编译和执行简单的用户定义代码

转载 作者:太空宇宙 更新时间:2023-11-03 15:31:47 25 4
gpt4 key购买 nike

我想让我的用户能够为项目运行非常简单的 Python 函数。当然,eval() 会浮现在脑海中,但这是一个巨大的风险。想了想,发现用户可能需要的功能,大部分都很简陋,类似于最常见的excel功能。所以我在想维护一个字典,其中键是函数名称,用户只能选择在该字典中定义的函数(由我)。例如:

def add(a, b):
return a + b

def sum(numbers):
result = 0
for number in numbers:
result += number
return number

...

function_map = {
'add': add,
'sum': sum,
...
}

现在,如果用户将一行定义为 add(4, 5),结果是预期的 9,但是,如果他们定义类似 foo(4),由于我的字典中不存在该键,因此会引发错误。我的问题是:这有多安全?我在这里忽略了任何潜在的漏洞吗?

最佳答案

您可以通过使用适当的globalslocals 参数来消除eval 某种程度上。例如,这是我在 a kind of calculator 中使用的 wat .

# To make eval() less dangerous by removing access
# to built-in functions.
_globals = {"__builtins__": None}
# But make standard math functions available.
_lnames = (
'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'e', 'log',
'log10', 'pi', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'radians'
)
_locals = {k: eval('math.' + k) for k in _lnames}

value = eval(expr, _globals, _locals)

但您可能也应该事先筛选表达式。拒绝那些包含 importevalexec 的:

if any(j in expr for j in ('import', 'exec', 'eval')):
raise ValueError('import, exec and eval are not allowed')

上面链接的模块还包含使用 ast 将 Python 计算转换为 LaTeX 数学表达式。您还可以使用 ast 构建自定义表达式计算器。

否则,这里是一个小的基于栈的postfix expression evaluator我做的。

一个区别是我将每个运算符需要的参数数量添加到 _ops 值中,这样我就知道要从堆栈中取出多少操作数。

import operator
import math

# Global constants {{{1
_add, _sub, _mul = operator.add, operator.sub, operator.mul
_truediv, _pow, _sqrt = operator.truediv, operator.pow, math.sqrt
_sin, _cos, _tan, _radians = math.sin, math.cos, math.tan, math.radians
_asin, _acos, _atan = math.asin, math.acos, math.atan
_degrees, _log, _log10 = math.degrees, math.log, math.log10
_e, _pi = math.e, math.pi
_ops = {
'+': (2, _add),
'-': (2, _sub),
'*': (2, _mul),
'/': (2, _truediv),
'**': (2, _pow),
'sin': (1, _sin),
'cos': (1, _cos),
'tan': (1, _tan),
'asin': (1, _asin),
'acos': (1, _acos),
'atan': (1, _atan),
'sqrt': (1, _sqrt),
'rad': (1, _radians),
'deg': (1, _degrees),
'ln': (1, _log),
'log': (1, _log10)
}
_okeys = tuple(_ops.keys())
_consts = {'e': _e, 'pi': _pi}
_ckeys = tuple(_consts.keys())


def postfix(expression): # {{{1
"""
Evaluate a postfix expression.

Arguments:
expression: The expression to evaluate. Should be a string or a
sequence of strings. In a string numbers and operators
should be separated by whitespace

Returns:
The result of the expression.
"""
if isinstance(expression, str):
expression = expression.split()
stack = []
for val in expression:
if val in _okeys:
n, op = _ops[val]
if n > len(stack):
raise ValueError('not enough data on the stack')
args = stack[-n:]
stack[-n:] = [op(*args)]
elif val in _ckeys:
stack.append(_consts[val])
else:
stack.append(float(val))
return stack[-1]

关于python - 在 Python 中编译和执行简单的用户定义代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57602836/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com