python3 读写大文件

python3 读写大文件

import os 

file_path =  "/home/Qwen3-Embedding-0.6B_external.mlir"

from functools import partial, wraps
from typing import TextIO, Callable


def chunked_file_reader(fp: TextIO, block_size: int=1024 * 8):
    for chunk in iter(partial(fp.read, block_size), ''):
        yield chunk


def read_file(file_path: str) -> int:
    count: int = 0
    with open(file_path) as f_read:
        for chunk in chunked_file_reader(f_read):
            count += 1
            # if(581500 <= count <= 581800):
            # if(581500 <= count):
            #     print(chunk)
            # if("tensor<3844x1xf16>" in chunk and "stc.matmul" in chunk):
            if("matmul" in chunk):
                print(chunk)
              # Remove this break to read the entire file
    return count

if __name__ == "__main__":
    if os.path.exists(file_path):
        print(f"File {file_path} exists, reading...")
        count = read_file(file_path)
        print(f"Total chunks read: {count}")
    else:
        print(f"File {file_path} does not exist.")

在代码

def chunked_file_reader(fp: TextIO, block_size: int=1024 * 8): 

中,block_size 参数定义了 每次从文件中读取的字节数,它是文件分块处理的核心控制参数。

1. block_size 的技术定义

作用:指定每次调用 fp.read() 时读取的最大字节数。
默认值:1024 * 8(即8KB),这是一个经验值,平衡了内存效率和I/O性能。
单位:字节(Bytes)。

2. 工作原理

for chunk in iter(partial(fp.read, block_size), ''):
    yield chunk
fp.read(block_size):

每次从文件对象 fp 中读取最多 block_size 字节的数据。
iter + partial:组合使用,持续读取直到返回空字符串('',表示文件结束)。
生成器:通过 yield 逐块返回数据,避免一次性加载整个文件。

3. 为什么需要分块?

场景 不分块的问题 分块的优点
大文件处理(如GB级日志) 内存爆满(OOM) 固定内存占用(仅 block_size 大小)
网络传输 延迟高,吞吐不稳定 平滑数据流,减少延迟峰值
实时处理 必须等待整个文件加载完毕 边读取边处理

4. block_size 的取值建议

取值 适用场景 注意事项
1KB~8KB 常规文本文件(如日志、CSV) 默认值通常是安全的选择
64KB~1MB 二进制文件(如图片、视频) 需测试内存与IPS(每秒操作数)的平衡
<1KB 内存极度受限环境(嵌入式) 可能增加I/O开销

6. 与其他参数的协同

文件系统块大小:通常为4KB(SSD)或1KB(HDD),匹配 block_size 可减少物理I/O次数。
磁盘缓存:大于缓存大小时(如Linux默认30%内存),分块读取仍能避免内存压力。

7. 实际应用示例

案例1:逐块处理大CSV

import csv

def process_large_csv(file_path):
    with open(file_path, 'r') as fp:
        reader = csv.reader(chunked_file_reader(fp, block_size=8192))
        for row in reader:
            process(row)  # 假设的逐行处理函数

案例2:HTTP分块上传

import requests

def upload_large_file(url, file_path):
    with open(file_path, 'rb') as fp:
        for chunk in chunked_file_reader(fp, block_size=64*1024):
            requests.post(url, data=chunk)

总结

block_size 是 内存效率 和 I/O效率 的权衡参数:
较小值:内存友好,但可能增加I/O次数。
较大值:减少I/O次数,但占用更多内存。

推荐实践:
默认使用 8KB(尤其文本处理)。
对二进制文件可尝试 64KB~1MB。
在资源受限环境中测试后调整。

posted @ 2025-06-11 15:04  michaelchengjl  阅读(30)  评论(0)    收藏  举报