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

Python中不加载整个文件到内存读取指定行的方法

绝对有办法解决这个问题!9万行2万列的CSV直接全加载确实会吃光内存,下面分两种情况给你方案——不换格式的应急办法,以及换格式的长期优化方案:

不修改文件格式:直接读取特定行

这种方法不需要改动原文件,完全靠逐行遍历筛选,内存占用极低,只保留你需要的行数据。

用Python内置csv模块(最省内存)

这是最稳妥的方案,csv模块天生就是逐行处理的,不会把整个文件塞进内存。你只需要把目标行的索引存成一个集合(查找更快),然后遍历每一行,匹配到就保留,甚至可以找到所有目标行后提前退出,节省时间:

import csv

# 把你要读取的行索引存在集合里(注意:行号从0开始,第一行是表头的话,数据行从1开始)
target_row_indices = {100, 2000, 50000}
selected_rows = []

with open('your_large_file.csv', 'r', newline='') as csv_file:
    reader = csv.reader(csv_file)
    for row_num, row in enumerate(reader):
        if row_num in target_row_indices:
            selected_rows.append(row)
            # 所有目标行都找到了就提前结束,不用再读后面的内容
            if len(selected_rows) == len(target_row_indices):
                break

# 现在selected_rows里就是你要的行数据了

用Pandas的skiprows参数(更便捷)

如果你习惯用Pandas处理数据,也可以用read_csv的skiprows参数,传入一个lambda函数来跳过不需要的行。本质上也是逐行遍历,但会帮你把结果整理成DataFrame:

import pandas as pd

target_row_indices = {100, 2000, 50000}
# skiprows返回True就跳过该行,所以我们只保留在目标集合里的行
df = pd.read_csv('your_large_file.csv', skiprows=lambda x: x not in target_row_indices)

注意:这里的行号也是从0开始的,如果你的CSV有表头,记得根据实际情况调整目标索引(比如表头是行0,数据行从1开始)。

更换文件格式:长期高效解决方案

如果需要频繁读取特定行/列,换成支持随机访问的格式会更高效,不用每次都遍历整个文件。推荐这几种:

Parquet(首推!)

Parquet是列存储格式,压缩率极高(比CSV小很多),而且支持直接按行索引读取,速度超快。只需要把CSV转成Parquet一次,之后读取就很方便:

第一步:把CSV转成Parquet

如果原文件太大,没法一次性加载到内存,可以分块读取再合并写入:

import pandas as pd

# 分块读取CSV,每块1万行
chunk_size = 10000
chunks = []
for chunk in pd.read_csv('your_large_file.csv', chunksize=chunk_size):
    chunks.append(chunk)

# 合并所有块并写入Parquet
full_df = pd.concat(chunks)
full_df.to_parquet('your_large_file.parquet')

第二步:读取特定行

转完之后,直接指定行索引就能读取,不用遍历整个文件:

import pandas as pd

# 直接读取指定行,秒出结果
selected_df = pd.read_parquet('your_large_file.parquet', rows=[100, 2000, 50000])

SQLite数据库(适合复杂查询)

如果需要经常做条件查询(不是只按行号),把数据导入SQLite数据库是个好选择。SQLite是文件型数据库,不需要额外安装服务,用Python就能直接操作:

第一步:把CSV导入SQLite

import sqlite3
import csv

# 连接到数据库文件(不存在会自动创建)
conn = sqlite3.connect('large_file_db.sqlite')
cursor = conn.cursor()

# 读取CSV表头,创建表结构
with open('your_large_file.csv', 'r', newline='') as csv_file:
    reader = csv.reader(csv_file)
    headers = next(reader)
    # 生成建表语句,默认所有列设为文本类型,你可以根据实际数据调整
    create_table_sql = f"CREATE TABLE IF NOT EXISTS data ({', '.join([f'{col} TEXT' for col in headers])})"
    cursor.execute(create_table_sql)
    
    # 分块插入数据,避免内存溢出
    chunk_size = 10000
    chunk = []
    for row in reader:
        chunk.append(tuple(row))
        if len(chunk) == chunk_size:
            cursor.executemany(f"INSERT INTO data VALUES ({', '.join(['?']*len(headers))})", chunk)
            chunk = []
    # 插入剩余的数据
    if chunk:
        cursor.executemany(f"INSERT INTO data VALUES ({', '.join(['?']*len(headers))})", chunk)
    
    conn.commit()

# 关闭连接
conn.close()

第二步:查询特定行

之后你就可以用SQL语句精准查询需要的行,比如按行号(SQLite自带rowid字段,从1开始):

import sqlite3

target_row_ids = [101, 2001, 50001]  # 对应原CSV的第100、2000、50000行数据(因为rowid从1开始,表头是rowid=1)
conn = sqlite3.connect('large_file_db.sqlite')
cursor = conn.cursor()

# 执行查询
cursor.execute(f"SELECT * FROM data WHERE rowid IN ({', '.join(['?']*len(target_row_ids))})", target_row_ids)
selected_rows = cursor.fetchall()

# 关闭连接
conn.close()

HDF5格式(传统大文件存储)

HDF5也是常用的大文件存储格式,支持随机访问,Pandas原生支持:

转格式并读取

import pandas as pd

# 转成HDF5(同样可以分块写入)
with pd.HDFStore('your_large_file.h5') as store:
    store['data'] = pd.read_csv('your_large_file.csv')

# 读取特定行
with pd.HDFStore('your_large_file.h5') as store:
    selected_df = store['data'].iloc[[100, 2000, 50000]]

不过HDF5的压缩率和跨平台性不如Parquet,现在更推荐用Parquet。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:47:39