6.0 KiB
RestrictedEnv 类技术文档
概述
RestrictedEnv 是一个轻量级的沙箱环境类,用于在受限上下文中安全地执行与日期/时间相关的表达式。它通过注册特定函数并利用 Python 的 exec 动态执行字符串形式的代码,提供了一种简洁的方式来解析和计算时间表达式,同时避免直接暴露完整的 Python 执行环境。
该类主要适用于需要动态解析时间表达式的场景(如配置文件、规则引擎等),且希望限制可调用函数范围以增强安全性。
依赖
appPublic.timeUtils as tu:提供日期/时间格式化与解析工具函数。datetime as dt:Python 标准库中的datetime模块,用于处理日期和时间对象。
⚠️ 注意:确保
appPublic.timeUtils模块已正确安装并包含所需方法。
类定义
class RestrictedEnv:
构造函数 __init__
初始化 RestrictedEnv 实例,并注册一组预定义的时间相关函数到内部命名空间。
注册的函数:
| 函数名 | 对应方法 | 描述 |
|---|---|---|
today |
self.today() |
返回今天的日期(仅年月日) |
date |
self.date(dstr) |
将字符串转换为日期对象 |
datetime |
self.datetime(dstr) |
将字符串转换为 datetime 对象 |
now |
dt.datetime.now(原生) |
获取当前精确到微秒的日期时间 |
示例:
env = RestrictedEnv()
# 此时 env 已经可以识别 'today()', 'date(...)', 'datetime(...)', 'now()' 等表达式
方法说明
reg(k: str, v: callable) -> None
将键值对 (k, v) 注册到实例的命名空间中,使得后续可通过字符串表达式调用 v。
参数:
k(str): 在表达式中使用的函数或变量名称。v(callable): 可调用对象(函数、方法、lambda 等)或数据。
实现方式:
使用 self.__dict__[k] = v 将其注入局部作用域。
示例:
ns.reg('pi', 3.14159)
result = ns.run('pi * 2') # 返回 6.28318
run(dstr: str) -> Any
在受限环境中执行给定的表达式字符串,并返回其结果。
参数:
dstr(str): 要执行的表达式字符串(如'today()',"date('2023-01-01')")。
返回值:
表达式计算的结果。
原理:
- 将输入表达式包装为赋值语句:
__tempkey__ = <表达式> - 使用
exec()在全局globals()和实例局部命名空间self.__dict__中执行。 - 返回临时变量
self.__tempkey__的值。
✅ 安全提示:虽然名为“受限”,但由于使用了
exec,仍需谨慎处理不可信输入,防止代码注入风险。
示例:
result = ns.run("today()") # 返回今天日期(Date 类型)
result = ns.run("now()") # 返回当前 datetime 对象
today() -> date
获取当前日期(仅年-月-日部分),忽略时间信息。
返回:
date对象,由tu.ymdDate(year, month, day)生成。
内部逻辑:
now = dt.datetime.now()
return tu.ymdDate(now.year, now.month, now.day)
示例:
ns.run("today()") # 输出类似: 2025-04-05
date(dstr: str) -> date
将日期字符串转换为日期对象。
参数:
dstr(str): 格式化的日期字符串,例如'2023-12-25'
返回:
date对象,由tu.str2Date(dstr)解析得到。
示例:
ns.run("date('2023-01-01')") # 返回对应日期对象
datetime(dstr: str) -> datetime
将日期时间字符串转换为 datetime 对象。
参数:
dstr(str): 包含时间和日期的字符串,如"2023-06-15 14:30:00"
返回:
datetime对象,由tu.str2Datetime(dstr)解析生成。
示例:
ns.run('datetime("2023-07-04 12:00:00")')
使用示例
以下是在主模块中运行的测试代码:
if __name__ == '__main__':
ns = RestrictedEnv()
a = ns.run('today()') # 当前日期
b = ns.run("date('2011-10-31')") # 自定义日期对象
c = ns.run('datetime("2012-03-12 10:22:22")') # 自定义 datetime
d = ns.run('now()') # 当前完整时间戳
预期输出类型:
| 表达式 | 返回类型 | 示例值 |
|---|---|---|
today() |
date |
2025-04-05 |
date(...) |
date |
2011-10-31 |
datetime(...) |
datetime |
2012-03-12 10:22:22 |
now() |
datetime |
2025-04-05 10:15:30.123456 |
安全性说明
⚠️ 警告:尽管称为“受限环境”,但因使用了 exec(),若传入恶意字符串可能导致任意代码执行。
建议:
- 仅用于可信输入或受控环境。
- 不应用于解析用户提交的表达式,除非有额外语法校验层。
- 可考虑替换为更安全的表达式解析器(如
asteval,simpleeval)以提升安全性。
扩展建议
你可以通过继承或修改 reg 调用来扩展功能,例如添加数学函数、条件判断等:
import math
ns.reg('sqrt', math.sqrt)
result = ns.run('sqrt(16)') # 得到 4.0
但请始终注意作用域控制与安全性。
总结
RestrictedEnv 提供了一个简单而有效的方式,在隔离环境下动态求值时间表达式。适合集成于规则系统、报表脚本或配置驱动的应用程序中,作为时间处理的 DSL(领域专用语言)入口点。
| 特性 | 说明 |
|---|---|
| ✅ 易用性 | 支持自然的时间表达式写法 |
| ✅ 可扩展 | 通过 reg() 添加新函数 |
| ⚠️ 安全性 | 使用 exec,需防范注入风险 |
| 📦 轻量 | 无外部依赖(除 appPublic.timeUtils) |
✅ 推荐用途:内部工具、自动化脚本、配置解析器
❌ 不推荐用途:Web API 输入解析、不受信用户输入处理