apppublic/aidocs/CSVData.md
2025-10-05 11:23:33 +08:00

6.4 KiB
Raw Blame History

CSVData 类技术文档

CSVData 是一个用于读取和处理 CSV 文件的 Python 类,提供了两种读取模式:一次性加载全部数据(read())和逐行迭代处理(iterRead())。该类支持自定义字段名、跳过标题行和数据起始行,适用于灵活解析各种格式的 CSV 数据。


📦 模块依赖

import csv

使用标准库中的 csv 模块进行 CSV 文件解析。


🔧 类定义

class CSVData(csvfile, names=None, headline=0, dataline=1)

参数说明:

参数 类型 默认值 说明
csvfile str 必填 CSV 文件路径
names list 或 None None 自定义字段名称列表。若提供,则忽略文件中的标题行
headline int 0 标题行所在的行号(从 0 开始),仅在 namesNone 时使用
dataline int 1 实际数据开始的行号(从 0 开始)

📚 方法说明

1. __init__(self, csvfile, names=None, headline=0, dataline=1)

初始化 CSVData 实例,设置文件路径与解析参数。


2. read(self) -> list[dict]

以列表形式返回所有记录,每条记录是一个字典(键为字段名,值为对应列值)。

返回值:

  • list[dict]: 包含所有数据记录的列表,例如:
    [
        {'st_date': '2024-01-01', 'open_price': '100', ...},
        {'st_date': '2024-01-02', 'open_price': '102', ...},
        ...
    ]
    

工作流程:

  1. 打开 CSV 文件(二进制模式 'rb' ⚠️ 存在潜在问题,请见下方【⚠️ 注意事项】)
  2. 创建 csv.reader 对象
  3. 若未指定 names,则读取第 headline 行作为字段名
  4. 从第 dataline 行开始逐行构建字典记录并添加到结果列表中
  5. 关闭文件并返回数据

适合小到中等规模的数据集。


3. iterRead(self)

以流式方式逐行读取 CSV 文件,并触发事件回调函数。适用于大数据文件,避免内存溢出。

回调机制:

  • onBegin(): 在开始读取前调用(当前实现为空)
  • onRecord(rec): 每处理一行有效数据时调用
  • onFinish(): 成功完成读取后调用

异常处理:

  • 使用 try-except 捕获异常,确保文件关闭
  • 出现错误时重新抛出异常(但变量作用域有误,请见【⚠️ Bug 提示】)

推荐用于大型 CSV 文件处理。


4. onBegin(self)

钩子方法,在迭代读取开始前被调用。默认为空实现,可由子类重写。

当前代码中调用了 self.onBegin(),但该方法未定义 —— 应为 onReadBegin?请见下方 Bug 分析。


5. onRecord(self, rec)

每读取一条有效记录时调用此方法。

参数:

  • rec (dict): 当前行数据,形如 {字段名: 值}

默认行为:

打印当前记录(print(rec)

可继承此类并重写该方法以实现自定义逻辑(如入库、计算等)。


6. onFinish(self)

所有数据读取完成后调用。

默认行为:

打印 "onFinish() called"

可用于资源清理或结束通知。


🖥️ 示例用法

if __name__ == '__main__':
    import sys
    cd = CSVData(
        sys.argv[1],
        names=['st_date','open_price','max_price','min_price','close_price','volume','adj_price']
    )
    cd.iterRead()

说明:

  • 从命令行传入 CSV 文件路径
  • 使用自定义字段名,不依赖文件头部
  • 调用 iterRead() 流式输出每一行数据

⚠️ 注意事项与改进建议

Bug 与潜在问题

问题 描述 建议修复
1. onBegin() 调用错误 代码中调用 self.onBegin(),但实际定义的是 onReadBegin(),会导致 AttributeError onReadBegin 改名为 onBegin,或修正调用
2. 异常捕获语法错误 except exception as e:exception 应为 Exception(首字母大写) 改为 except Exception as e:
3. 文件打开模式冲突 read() 方法使用 'rb' 二进制模式打开文件,但 csv.reader 需要文本模式 改为 'r' 并指定编码(如 'utf-8'
4. fd.close() 变量作用域错误 except 块中调用 fd.close(),但 fd 是实例属性应写作 self.fd 改为 self.fd.close()
5. 缺少编码设置 未指定字符编码,可能导致中文乱码 添加 encoding='utf-8' 参数

推荐修改后的 iterRead() 示例:

def iterRead(self):
    self.fd = open(self.csvfile, 'r', encoding='utf-8')
    try:
        reader = csv.reader(self.fd)
        fields = None
        if self.names is not None:
            fields = self.names
        lno = 0
        self.onBegin()  # 确保方法存在
        for l in reader:
            if fields is None and lno == self.headline:
                fields = [f for f in l]
            if lno >= self.dataline:
                rec = {}
                for i in range(len(fields)):
                    rec[fields[i]] = l[i]
                self.onRecord(rec)
            lno += 1
        self.fd.close()
        self.onFinish()
    except Exception as e:
        self.fd.close()
        raise e

🧩 继承与扩展建议

可通过继承 CSVData 类来实现更复杂的功能:

class MyCSVProcessor(CSVData):
    def onBegin(self):
        print("开始处理数据...")

    def onRecord(self, rec):
        # 示例:过滤价格大于 100 的记录
        if float(rec['close_price']) > 100:
            print("高价值记录:", rec)

    def onFinish(self):
        print("数据处理完毕!")

📎 总结

特性 支持情况
自定义字段名
跳过标题行
指定数据起始行
全量读取 (read)
流式读取 (iterRead)
可扩展性 (支持回调钩子)
错误处理 ⚠️ 存在缺陷,需修复
编码支持 缺失,建议增加

📌 版本建议(改进方向)

  1. 增加 encoding 参数,默认 'utf-8'
  2. 修复异常捕获与方法命名
  3. 使用上下文管理器 (with open(...)) 替代手动关闭文件
  4. 添加类型注解提升可读性
  5. 支持分隔符参数(如 tab、分号等

📘 结论CSVData 是一个结构清晰、易于扩展的 CSV 处理类,稍作修正后可用于生产环境。