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

Python While循环语法错误排查及大CSV分批导入方案咨询

问题分析与解决方案

嗨,刚接触Python做论文研究就处理这么大的文件,已经很棒了!咱们先把代码里的问题捋清楚,再聊聊分批方案的合理性。

一、代码中的错误排查与修正

你的代码有几个语法和逻辑问题,我一个个拆解:

  1. While循环语法错误
    while length_rows = i 这里用了赋值符号=,应该改成相等判断==,而且while语句末尾必须加冒号,还要缩进后续代码:

    while length_rows == i:
    
  2. Try-Except配对错误
    你直接写了except KeyboardInterrupt,但没有对应的try块,这会直接触发语法错误。如果想捕获用户中断操作,需要把循环内的代码包裹在try块里;如果暂时不需要这个功能,可以先删掉这个except。

  3. 参数名拼写错误
    pandas的read_csv里跳过行的参数是skiprows(复数),你写成了skiprow,会导致参数识别失败。

  4. DataFrame.append已被弃用
    pandas的append方法早就被标记为弃用了,推荐用pd.concat来合并数据框,避免警告或报错。

  5. 表头不一致问题
    第一次读取数据时没加header=None,但后续读取加了,这会导致后续的data没有列名,调用data["mbaddr"]会直接报错。需要保持表头逻辑一致,要么第一次读取时保留表头,后续读取时复用这个表头。

  6. 未定义变量问题
    np_cod没有在函数内定义,要么把它作为函数参数传入,要么在函数内部赋值,不然运行时会报NameError。

  7. 筛选逻辑不一致
    第一次读取的原始数据没有做筛选就存入data_values了,后续才筛选,这可能不符合你的需求,应该统一筛选逻辑。

修正后的完整代码

import pandas as pd
import numpy as np

def screma_dati(file, np_cod):
    chunk_size = 1000000  # 用更直观的变量名
    print("\n...begin skimming...")
    # 第一次读取:获取列名并完成首次筛选
    data_values = pd.read_csv(file, nrows=chunk_size)
    data_values = data_values.loc[data_values["mbaddr"].isin(np_cod)]
    print(f"\n\t Dataset:\t{file}")
    print("\n\t part n: 1")
    
    j = chunk_size  # 记录已读取的总行数,用于后续跳过
    while True:
        try:
            # 后续读取:复用第一次的列名,跳过已读内容
            data = pd.read_csv(file, skiprows=j, nrows=chunk_size, header=None, names=data_values.columns)
            length_rows = data.shape[0]
            
            if length_rows == 0:
                break  # 没有剩余数据,退出循环
            
            # 筛选当前批次的数据
            filtered_data = data.loc[data["mbaddr"].isin(np_cod)]
            # 合并数据(替代弃用的append)
            data_values = pd.concat([data_values, filtered_data], ignore_index=True)
            
            j += chunk_size
            print(f"\n\t part n: {j // chunk_size}")
            
            # 如果读取的行数小于批次大小,说明是最后一批
            if length_rows < chunk_size:
                break
        except KeyboardInterrupt:
            print("\n...skimming interrupted by user...")
            return data_values
        except Exception as e:
            print(f"\nError occurred: {e}")
            break
    
    print("\n...end skimming...")
    return data_values

# 调用示例(需要先定义你的参考代码列表np_cod)
# np_cod = ["cod1", "cod2", "cod3"]
# final_data = screma_dati("your_large_file.csv", np_cod)

二、分批导入方案的合理性

你的分批导入思路完全正确!对于20GB的大型CSV,一次性加载到内存几乎不现实(除非你有超大内存),分批处理是这类场景下的标准解决方案,能有效避免内存溢出问题。

不过我推荐你试试pandas内置的chunksize参数,它可以更简洁地实现分批读取,不用手动计算跳过的行数:

def screma_dati_chunks(file, np_cod):
    chunk_size = 1000000
    data_values = pd.DataFrame()
    print("\n...begin skimming...")
    # 用chunksize自动分批读取
    for part_num, chunk in enumerate(pd.read_csv(file, chunksize=chunk_size), 1):
        print(f"\n\t part n: {part_num}")
        filtered_chunk = chunk.loc[chunk["mbaddr"].isin(np_cod)]
        data_values = pd.concat([data_values, filtered_chunk], ignore_index=True)
    
    print("\n...end skimming...")
    return data_values

这个写法更简洁,出错概率更低。如果想进一步优化性能,还可以:

  • 用dtype参数指定列的类型(比如把重复多的字符串列设为category类型),减少内存占用
  • 用usecols参数只读取需要的列,避免加载无关数据,节省时间和内存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:05:32