You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Polars将Python函数生成的数据流式写入Parquet文件?

如何用Polars流式写入批量生成的Parquet文件

我有一个Python脚本会对文件列表执行操作,生成的DataFrame约6GB,因此需要用Parquet压缩存储。问题在于数据是通过函数逐批生成的,不想先把所有数据存到内存里再拆分写入,希望能直接流式写入Parquet。我主要用Polars而非Pandas,求相关实现建议。

附上当前代码:

from time import sleep


def min_and_max(x: list[int]) -> tuple[int, int]:
    sleep(30)  # 模拟耗时操作
    return (min(x), max(x))


numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

for num in numbers:
    print(min_and_max(num))
    # 这里需要写入Parquet的逻辑
    # 把结果存在列表或其他数据结构里太占内存

方法1:分批追加写入Parquet

Polars支持写入Parquet时使用mode="append"参数,你可以每次生成一小批数据就直接写入文件,无需将全量数据驻留内存。

修改后的代码示例:

import polars as pl
from time import sleep


def min_and_max(x: list[int]) -> tuple[int, int]:
    sleep(30)  # 模拟耗时操作
    return (min(x), max(x))


numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
output_path = "results.parquet"

# 初始化:处理第一个批次并创建Parquet文件
first_num = numbers[0]
min_val, max_val = min_and_max(first_num)
df_first = pl.DataFrame({"min": [min_val], "max": [max_val]})
df_first.write_parquet(output_path)

# 处理剩余批次并追加写入
for num in numbers[1:]:
    min_val, max_val = min_and_max(num)
    df_batch = pl.DataFrame({"min": [min_val], "max": [max_val]})
    df_batch.write_parquet(output_path, mode="append")

注意:这种方式适合单条数据量极小的场景,但频繁追加可能会生成较多小文件块,后续读取时可通过pl.scan_parquet自动优化性能。

方法2:迭代器流式生成写入

如果希望更贴合流式处理的逻辑,可以把数据生成逻辑包装成迭代器,转换成Polars的LazyFrame后直接写入,全程内存占用极低:

import polars as pl
from time import sleep


def min_and_max(x: list[int]) -> tuple[int, int]:
    sleep(30)  # 模拟耗时操作
    return (min(x), max(x))


def data_generator(numbers_list):
    for num in numbers_list:
        min_val, max_val = min_and_max(num)
        yield {"min": min_val, "max": max_val}


numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

# 从迭代器创建流式LazyFrame
lf = pl.scan_batches(data_generator(numbers))

# 流式写入Parquet
lf.sink_parquet("results_streaming.parquet")

这种方式下,Polars会自动从迭代器逐批读取数据并写入文件,完全不需要加载全量数据到内存,适合处理大规模生成的数据。


额外优化建议

  • 调整批次大小:如果单条数据太小,可以攒N个结果再生成批次写入,减少IO次数提升效率,比如每处理100条数据写入一次。
  • 指定压缩算法:写入时可选择更高压缩比的算法(如zstd)进一步缩小文件体积:
    lf.sink_parquet("results_streaming.parquet", compression="zstd")
    
  • 显式指定Schema:提前定义数据结构,避免Polars自动推断的开销:
    schema = pl.Schema({"min": pl.Int64, "max": pl.Int64})
    lf = pl.scan_batches(data_generator(numbers), schema=schema)
    

内容的提问来源于stack exchange,提问作者Adrian Fletcher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:55:11