Python分块计算(Chunk Processing)详解:解决大规模数据内存溢出的工程实践

文章目录

在数据分析和工程计算中,我们经常会遇到一个问题:

数据量太大,一次性读入内存会直接崩溃。

例如:

  • 雷达扫描数据
  • 风电测风塔高频数据
  • 日志数据
  • 传感器数据

很多时候,一个 CSV 文件就可能达到:

  • 几 GB
  • 上千万行
  • 甚至上亿行

如果直接使用:

python 复制代码
df = pd.read_csv("data.csv")

很可能会遇到:

复制代码
MemoryError

或者程序运行到一半直接被系统杀死。

解决这个问题最有效的方法就是:

分块计算(Chunk Processing)

本文将深入浅出介绍 Python 分块计算的原理、实现方法以及工程实践。


一、什么是分块计算?

分块计算(Chunk Processing)是一种常见的大数据处理技术,其核心思想是:

不要一次性读取全部数据,而是分批读取、逐块处理。

假设有一个 1000 万行的 CSV 文件。

普通处理方式:

复制代码
一次读取
┌─────────────────────────┐
│      1000万行数据       │
└─────────────────────────┘

内存压力非常大。

而分块计算是:

复制代码
分块读取

┌────────────┐
│   10万行   │ → 处理 → 输出
└────────────┘

┌────────────┐
│   10万行   │ → 处理 → 输出
└────────────┘

┌────────────┐
│   10万行   │ → 处理 → 输出
└────────────┘

任何时候内存中只有一小块数据。

因此可以处理远大于内存容量的数据。


二、Python实现分块读取

Pandas 提供了一个非常方便的参数:

复制代码
chunksize

示例:

python 复制代码
import pandas as pd

reader = pd.read_csv("big_data.csv", chunksize=100000)

for chunk in reader:
    print(len(chunk))

这里:

复制代码
chunksize = 100000

表示:

每次只读取 10万行

返回的 reader 实际上是一个 迭代器

程序执行过程:

复制代码
第1次读取 10万行
第2次读取 10万行
第3次读取 10万行
...

三、一个简单示例

假设我们有一个很大的 CSV 文件:

复制代码
data.csv

内容:

复制代码
timestamp,wind_speed
2024-01-01 00:00,5.3
2024-01-01 00:01,6.1
...

目标:计算平均风速。

如果直接读取:

python 复制代码
df = pd.read_csv("data.csv")
print(df["wind_speed"].mean())

数据太大可能会崩溃。

分块计算方法:

python 复制代码
import pandas as pd

reader = pd.read_csv("data.csv", chunksize=100000)

total_sum = 0
total_count = 0

for chunk in reader:
    total_sum += chunk["wind_speed"].sum()
    total_count += len(chunk)

mean_ws = total_sum / total_count

print("平均风速:", mean_ws)

核心思想:

复制代码
sum += chunk.sum()
count += chunk.count()

最后再计算整体结果。

这样即使数据有 1亿行,也可以轻松处理。


四、分块计算的工程模式

在工程实践中,分块计算通常有三种模式。


1 分块统计

适用于:

  • 平均值
  • 最大值
  • 最小值
  • 计数
  • 分组统计

示例:

python 复制代码
total_sum += chunk.sum()
total_cnt += chunk.count()

最后计算:

复制代码
mean = sum / count

2 分块过滤

适用于:

  • 条件筛选
  • 数据清洗

例如:

python 复制代码
for chunk in pd.read_csv("data.csv", chunksize=100000):

    chunk = chunk[chunk["wind_speed"] > 10]

    chunk.to_csv("result.csv", mode="a", index=False)

这里使用:

复制代码
mode="a"

表示:

追加写入文件。

因此不会占用大量内存。


3 分块计算 + 实时写盘

这是工程中最常见的模式。

流程:

复制代码
读取一块数据
        ↓
数据处理
        ↓
写入结果文件
        ↓
释放内存

示例:

python 复制代码
for chunk in pd.read_csv("data.csv", chunksize=100000):

    result = process(chunk)

    result.to_csv(
        "output.csv",
        mode="a",
        header=False,
        index=False
    )

这样:

  • 内存始终很小
  • 处理速度也很快

五、真实工程案例:雷达数据处理

在风资源分析中,我们经常需要处理:

  • 扫描雷达数据
  • 高频测风塔数据

例如:

复制代码
Timestamp
Azimuth
Elevation
Distance
WindSpeed

假设数据量:

复制代码
100GB

如果直接读取:

复制代码
df = pd.read_csv()

基本必然崩溃。

正确方式是:

python 复制代码
for chunk in pd.read_csv(file, chunksize=200000):

    # 距离过滤
    chunk = chunk[
        (chunk["Distance"] >= 250) &
        (chunk["Distance"] <= 400)
    ]

    # 计算坐标
    chunk["x"] = ...
    chunk["y"] = ...
    chunk["z"] = ...

    # 写入结果
    chunk.to_csv("result.csv", mode="a")

优势:

  • 内存稳定
  • 可以处理 TB 级数据
  • 程序稳定性高

六、分块计算的性能优化

在实际工程中,还可以进一步优化。


1 只读取必要列

CSV 文件往往有很多列。

使用:

python 复制代码
pd.read_csv(
    file,
    usecols=["Timestamp", "Distance", "WindSpeed"],
    chunksize=100000
)

可以大幅降低内存。


2 使用 float32

默认:

复制代码
float64

占用:

复制代码
8 bytes

可以改为:

复制代码
float32

占用:

复制代码
4 bytes

示例:

python 复制代码
chunk["wind_speed"] = chunk["wind_speed"].astype("float32")

3 及时释放内存

处理完一个块后:

python 复制代码
del chunk
import gc
gc.collect()

可以避免内存逐渐增长。


4 使用 Parquet 代替 CSV

CSV:

  • 体积大
  • 读取慢

Parquet:

  • 更快
  • 更省空间
  • 支持列存储

示例:

python 复制代码
chunk.to_parquet("data.parquet")

七、什么时候必须使用分块计算?

当出现以下情况时,强烈建议使用分块计算:

数据规模:

复制代码
> 1GB
> 1000万行

或者:

  • 服务器内存较小
  • CSV 文件过大
  • 程序出现 MemoryError

分块计算几乎是唯一稳定方案


八、分块计算的本质

分块计算的本质其实就是:

流式计算(Streaming Processing)

核心思想:

复制代码
数据流入 → 处理 → 输出

而不是:

复制代码
全部加载 → 再处理

这也是:

  • Spark
  • Flink
  • Hadoop

等大数据系统的核心思想。


九、总结

Python 分块计算是处理大规模数据最实用的技术之一。

核心原则只有三条:

1 不一次性读取全部数据

复制代码
chunksize

2 分块处理

复制代码
for chunk in reader

3 实时写出结果

复制代码
mode="a"

通过分块计算,我们可以:

  • 处理 TB 级数据
  • 避免内存溢出
  • 提升程序稳定性

在工程实践中,这是一个非常重要的数据处理技巧。

相关推荐
Liu628882 小时前
Python单元测试(unittest)实战指南
jvm·数据库·python
晨非辰2 小时前
Linux终端输出哲学:从回车换行到进度条实战,掌握缓冲区刷新与ANSI控制,告别输出延迟焦虑
linux·运维·服务器·c++·人工智能·后端·自动化
lpfasd1232 小时前
2026年第12周GitHub趋势周报:Claude生态爆发,AI工程化加速,开发者工具链重构
人工智能·重构·github
我的xiaodoujiao2 小时前
4、API 接口自动化测试详细图文教程学习系列4--相关Python基础知识3
python·学习·测试工具·pytest
Meepo_haha2 小时前
python的sql解析库-sqlparse
数据库·python·sql
无巧不成书02182 小时前
【开源AI视频笔记工具】BiliNote部署教程:本地+Docker双方案,小白也能轻松上手!
人工智能·开源·音视频·bilinote部署教程·cookie获取
岁岁种桃花儿2 小时前
AI超级智能开发系列从入门到上天第六篇:自定义AI记忆持久化
数据库
夏日清风有你2 小时前
MNIST手写数字图像
python
黄昏回响2 小时前
计算机系统基础知识(补充篇):数据库——数据仓库、数据中台与大数据技术详解
大数据·数据库·数据仓库