
本文介绍一种仅依赖标准库、无需第三方包的动态数据查询方法:通过安全封装 eval() 实现类似 SQL 的灵活条件过滤,适用于 CSV 解析后的列表数据,支持任意字段索引与混合比较运算符。
本文介绍一种仅依赖标准库、无需第三方包的动态数据查询方法:通过安全封装 `eval()` 实现类似 sql 的灵活条件过滤,适用于 csv 解析后的列表数据,支持任意字段索引与混合比较运算符。
在缺乏 Pandas 或 SQLite 等外部库的受限环境中(如嵌入式脚本、沙箱环境或严格合规场景),仍需对结构化数据(如 CSV 解析后的行列表)执行动态条件查询——例如“筛选第2列等于2且第4列不为5的行”,或“第7列是字符串‘Bob’且第13列大于等于0”。这类需求本质上要求运行时解析并执行用户定义的布尔逻辑,而 Python 标准库中的 eval() 正是解决该问题的核心工具。
以下是一个生产就绪的轻量级查询函数:
from collections.abc import Sequence
from typing import Any, Tuple
def query_data(
data: Sequence[Tuple[Any, ...]],
condition: str,
*,
allow_callables: bool = False
) -> Sequence[Tuple[Any, ...]]:
"""
基于动态条件表达式过滤数据行。
Args:
data: 元组序列(如 csv.reader 输出),每行代表一条记录
condition: 以 'row' 为行变量的合法 Python 表达式,返回布尔值
allow_callables: 是否允许调用内置函数(如 isinstance, len, str.startswith)
Returns:
满足条件的行组成的列表
"""
# 限制可用命名空间,提升安全性
safe_globals = {"__builtins__": {}}
if allow_callables:
safe_globals.update({
"isinstance": isinstance,
"len": len,
"str": str,
"int": int,
"float": float,
"bool": bool,
"None": None,
})
return [
row for row in data
if eval(condition, safe_globals, {"row": row})
]
✅ 使用示例(模拟 CSV 数据):
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
csv_data = [
(1, 2, 3, 4, 5),
(1, 2, 3, 5, 5),
(10, 9, 8, 7, 6),
("Alice", None, "Bob", 0, -1),
("Bob", "Alice", "Charlie", 0, 1),
("Daniel", None, "Evan", 1, 0),
]
# 多样化查询
print(query_data(csv_data, "row[1] == 2 and row[3] != 5"))
# → [(1, 2, 3, 4, 5)]
print(query_data(csv_data, "row[0] == 'Bob' and row[1] is not None and row[3] >= 0"))
# → [("Bob", "Alice", "Charlie", 0, 1)]
print(query_data(csv_data, "isinstance(row[0], str) and row[0].startswith('A')"))
# → [("Alice", None, "Bob", 0, -1)]
⚠️ 关键注意事项:
- 安全性第一:eval() 默认可执行任意代码,必须严格限制 globals 和 locals。本实现默认禁用所有内置函数,仅当显式启用 allow_callables=True 时才开放少数安全函数。
- None 比较:务必使用 is None 或 is not None 判断空值(而非 == None),避免自定义类重载 __eq__ 导致意外行为。
- 字段索引越界:若条件中访问 row[100] 而某行长度不足,将抛出 IndexError。建议预处理数据确保行列一致性,或在外层添加异常捕获。
- 性能考量:对大数据集,此方法为 O(n×m) 时间复杂度(n 行 × m 条件解析开销)。若性能敏感,应考虑预编译条件(如 compile(condition, '', 'eval') 复用 code object)。
该方案本质是将“查询逻辑”从硬编码解耦为字符串配置,配合 CSV 解析器(如 csv.reader)即可快速构建可配置的数据筛选管道,兼顾灵活性、可维护性与标准库兼容性。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










