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

Python处理大文件时进程被终止的解决方法咨询

问题描述

我编写了如下脚本:

import pandas as pd

import os
import glob

novas_colunas = [
    'UF', 'Municipios', 'Área de Ponderação', 'Controle', 'Peso Amostral', 'Região Geográfica', 'Mesorregião', 'Microrregião',
    'Código da Região Metropolitana', 'Situação do Domicilio', 'Espécie de Unidade Visitada','Tipo de Espécie',
    'Condição de Ocupação', 'Valor do Aluguel', 'Aluguel em número de salários', 'Material Predominante', 'Nº de Cômodos',
    'Densidade de Morador', 'Cômodos  com dormitórios', 'Densidade de morador dormitório','Nº de Banheiros', 'Sanitários', 'Tipo de Esgotamento Sanitário', 'Forma de Abastecimento de Água',
    'Canalização', 'Destino do Lixo', 'Existênia de Energia Elétrica',
    'Existência de Medidor de Energia', 'Rádio', 'Televisão', 'Máquina de Lavar',
    'Geladeira', 'Celular', 'Telefone Fixo', 'Microcomputador', 'Microcomputador com internet', 'Motocicleta', 'Automóvel',
    'ALGUMA PESSOA QUE MORAVA COM VOCÊ(S) ESTAVA MORANDO EM OUTRO PAÍS EM 31 DE JULHO DE 2010',
    'QUANTAS PESSOAS MORAVAM NESTE DOMICÍLIO EM 31 DE JULHO DE 2010', 'A RESPONSABILIDADE PELO DOMICÍLIO É DE',
    'DE AGOSTO DE 2009 A JULHO DE 2010, FALECEU ALGUMA PESSOA QUE MORAVA COM VOCÊ(S)',
    'Rendimento Mensal pelo domicilio em Julho de 2010',
    'RENDIMENTO DOMICILIAR, SALÁRIOS MÍNIMOS, EM JULHO DE 2010',
    'RENDIMENTO DOMICILIAR PER CAPITA EM JULHO DE 2010',
    'RENDIMENTO DOMICILIAR PER CAPITA, EM Nº DE SALÁRIOS    MÍNIMOS, EM JULHO DE 2010',
    'Espécie da Unidade Doméstica', 'ADEQUAÇÃO DA MORADIA', 'MARCA DE IMPUTAÇÃO NA V0201:',
    'MARCA DE IMPUTAÇÃO NA V2011:', 'MARCA DE IMPUTAÇÃO NA V0202:', 'MARCA DE IMPUTAÇÃO NA V0203',
    'MARCA DE IMPUTAÇÃO NA V0204', 'MARCA DE IMPUTAÇÃO NA V0205','MARCA DE IMPUTAÇÃO NA V0206',
    'MARCA DE IMPUTAÇÃO NA V0207', 'MARCA DE IMPUTAÇÃO NA V0208', 'MARCA DE IMPUTAÇÃO NA V0209',
    'MARCA DE IMPUTAÇÃO NA V0210', 'MARCA DE IMPUTAÇÃO NA V0211', 'MARCA DE IMPUTAÇÃO NA V0212',
    'MARCA DE IMPUTAÇÃO NA V0213', 'MARCA DE IMPUTAÇÃO NA V0214', 'MARCA DE IMPUTAÇÃO NA V0215',
    'MARCA DE IMPUTAÇÃO NA V0216', 'MARCA DE IMPUTAÇÃO NA V0217', 'MARCA DE IMPUTAÇÃO NA V0218',
    'MARCA DE IMPUTAÇÃO NA V0219', 'MARCA DE IMPUTAÇÃO NA V0220', 'MARCA DE IMPUTAÇÃO NA V0221',
    'MARCA DE IMPUTAÇÃO NA V0222', 'MARCA DE IMPUTAÇÃO NA V0301', 'MARCA DE IMPUTAÇÃO NA V0401',
    'MARCA DE IMPUTAÇÃO NA V0402', 'MARCA DE IMPUTAÇÃO NA V0701', 'SITUAÇÃO DO SETOR']

pasta = 'saida-microdados/*.csv'
arquivos = []
for i in glob.glob(pasta):
  arquivos.append(i)

for i in range(len(arquivos)):
  dataf = pd.read_csv(arquivos[i])
  velhas_colunas = dataf.columns
  dataf.rename(columns = dict(zip(velhas_colunas, novas_colunas)), inplace = 'True')
  dataf.to_csv(arquivos[i])

文件夹内有大量大体积CSV文件,脚本无输出信息,无法追踪处理进度,手动检查发现仅少数文件完成列名修改,大部分未处理。尝试过pypy、列表推导式优化均无效,还有一个生成这些CSV的TXT处理脚本也出现进程中途终止的问题。需要找到最佳解决方案。

解决方案

1. 修复代码低级错误

你的rename方法中inplace='True'传入的是字符串而非布尔值,这会导致逻辑异常,直接修改为inplace=True,这是部分文件未处理的核心原因之一。

2. 改用低内存的表头修改方案

无需加载整个大文件到内存,仅修改CSV表头即可,内存占用极低,适合超大文件:

import glob
import logging
import os

# 配置日志,记录进度和错误
logging.basicConfig(
    filename='csv_rename_log.txt',
    level=logging.INFO,
    format='%(asctime)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

novas_colunas = [
    # 保留你的列名列表
    'UF', 'Municipios', 'Área de Ponderação', ...
]

pasta = 'saida-microdados/*.csv'
arquivos = glob.glob(pasta)
total_arquivos = len(arquivos)

# 读取已处理文件,避免重复操作
processed_files = set()
try:
    with open('csv_rename_log.txt', 'r') as f:
        for line in f:
            if '成功处理文件' in line:
                processed_files.add(line.split(': ')[-1].strip())
except FileNotFoundError:
    pass

for idx, arquivo in enumerate(arquivos, 1):
    if arquivo in processed_files:
        logging.info(f"跳过已处理文件:{arquivo}")
        continue
        
    try:
        logging.info(f"开始处理文件 {idx}/{total_arquivos}: {arquivo}")
        # 读取原表头并验证列数匹配
        with open(arquivo, 'r', encoding='utf-8') as f_in:
            original_header = f_in.readline().strip().split(',')
            if len(original_header) != len(novas_colunas):
                logging.error(f"文件{arquivo}列数不匹配:原列数{len(original_header)},目标列数{len(novas_colunas)},跳过")
                continue
            new_header = ','.join(novas_colunas) + '\n'
            
            # 逐行写入临时文件
            with open(f"{arquivo}.tmp", 'w', encoding='utf-8') as f_out:
                f_out.write(new_header)
                for line in f_in:
                    f_out.write(line)
        
        # 替换原文件
        os.replace(f"{arquivo}.tmp", arquivo)
        logging.info(f"成功处理文件 {idx}/{total_arquivos}: {arquivo}")
    except Exception as e:
        logging.error(f"处理文件{arquivo}失败:{str(e)}")
        # 清理临时文件
        if os.path.exists(f"{arquivo}.tmp"):
            os.remove(f"{arquivo}.tmp")

3. 解决进程终止问题

  • 内存不足:上面的逐行处理方法彻底避免了大内存占用,不会因内存耗尽被系统杀死。
  • IO瓶颈:将文件转移到SSD存储,或分批处理(比如每次处理10个文件,处理完再继续下一批)。
  • 系统资源限制:检查系统是否有进程内存配额(如Linux的ulimit),适当调整上限;多进程处理需注意IO冲突,单进程逐文件处理更稳定。

4. TXT转CSV脚本优化思路

和CSV重命名逻辑一致,采用逐行读取-逐行写入的方式,同时添加日志和错误捕获,即使中途中断,也能从日志中定位未处理的文件,后续可直接跳过已完成的部分。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:50:57