0

0

Python CSV文件清洗与转换:跳过无效行、替换字符与编码转换实战

聖光之護

聖光之護

发布时间:2025-12-04 12:41:01

|

500人浏览过

|

来源于php中文网

原创

Python CSV文件清洗与转换:跳过无效行、替换字符与编码转换实战

本教程旨在指导您如何使用python高效处理结构不规范的csv文件,解决常见的清洗与转换问题。内容涵盖如何移除空行或特定格式的无效行、添加新文件头、更改数据分隔符、批量替换特定字符,以及进行文件编码转换。通过实用的代码示例和错误解析,帮助您掌握处理复杂csv数据的专业技巧,避免常见的i/o和数据类型错误。

引言:CSV文件处理的常见挑战

在数据处理过程中,我们经常会遇到格式不规范的CSV文件。这些文件可能包含多余的空行、分隔符不一致、特定字符需要替换,甚至编码格式也与预期不符。直接使用这些数据往往会导致解析错误或数据处理逻辑混乱。例如,尝试在已关闭的文件对象上进行读写操作(ValueError: I/O operation on closed file.)或对不支持该方法的对象调用字符串方法(AttributeError: 'list' object has no attribute 'split')是新手常犯的错误。

本教程将详细讲解如何使用Python的csv模块,结合文件I/O操作,高效且鲁棒地解决以下常见的CSV文件处理需求:

  1. 删除或跳过文件开头或内容中无用的行。
  2. 为输出文件添加新的自定义标题行。
  3. 将文件内的分隔符从逗号(,)转换为分号(;)。
  4. 将数据字段中的特定字符(如连字符-)替换为其他字符(如分号;)。
  5. 将输入文件的编码从UTF-16转换为UTF-8,并生成新的文件。

理解常见的Python文件操作错误

在深入解决方案之前,我们首先需要理解两个常见的错误,它们通常源于对Python文件操作和数据类型的不当使用:

1. ValueError: I/O operation on closed file.

这个错误通常发生在尝试对一个已经关闭的文件对象进行读写操作时。在Python中,使用with open(...) as file_object:语句可以确保文件在代码块执行完毕后自动关闭,即使发生异常也不例外。一旦with块结束,file_object就会被关闭,无法再进行I/O操作。

立即学习Python免费学习笔记(深入)”;

错误示例:

with open('input.csv', 'r') as read_file:
    # 在这里可以读取文件
    lines = read_file.readlines()

# read_file 在此处已经关闭
for line in read_file: # 尝试再次读取,将导致 ValueError
    print(line)

正确做法: 确保所有对文件对象的读写操作都在with块内部完成,或者在文件关闭前将所需数据加载到内存中。

2. AttributeError: 'list' object has no attribute 'split'

split()是一个字符串方法,用于根据指定的分隔符将字符串分割成一个字符串列表。这个错误表明您正在尝试对一个列表对象(而不是字符串对象)调用split()方法。

错误示例:

lines = [] # 这是一个列表
lines_ = lines.split('-') # 尝试对列表调用 split() 方法,将导致 AttributeError

正确做法: 确保您是在字符串上调用split()方法。当处理CSV数据时,csv.reader会返回行(row)作为列表,列表中的每个元素都是一个字符串。如果需要对某个字段(即列表中的一个字符串元素)进行分割,应单独对其调用split()。

解决方案:逐步处理CSV文件

我们将采用一种高效且内存友好的方法,即逐行读取输入文件,处理后立即写入输出文件,而不是将所有数据一次性加载到内存中。

Nimo.space
Nimo.space

智能画布式AI工作台

下载

1. 准备输入文件与核心处理逻辑

假设我们的input.csv文件包含以下内容:

empty line
empty line
------------------------------------
cars,Date,Daypart,'000 (avg),Share (excluded: Other))
car1,2022-01-01,02:00-02:00,24.459,4.3
car1,2022-01-01,02:01-02:01,20.967,3.7

我们的目标是:

  • 删除前几行(如空行和全连字符行)。
  • 添加新的标题。
  • 将逗号分隔符改为分号。
  • 将数据中的连字符-改为分号;。
  • 将UTF-16编码转换为UTF-8。

2. 实现代码

以下是实现上述所有需求的Python代码:

import csv

def process_csv_file(input_filepath, output_filepath, new_header):
    """
    处理CSV文件,包括删除无效行、更改分隔符、替换字符和转换编码。

    Args:
        input_filepath (str): 输入CSV文件的路径。
        output_filepath (str): 输出CSV文件的路径。
        new_header (list): 新的标题行列表。
    """
    try:
        # 同时打开输入和输出文件,确保资源管理得当
        # 注意:input.csv 假定为 UTF-16 编码
        with open(input_filepath, 'r', encoding="utf-16") as read_file, \
             open(output_filepath, 'w', newline='', encoding="utf-8") as write_file:

            # 初始化 CSV 读取器,使用逗号作为原始分隔符
            reader = csv.reader(read_file, delimiter=",")
            # 初始化 CSV 写入器,使用分号作为新的分隔符
            writer = csv.writer(write_file, delimiter=";")

            # 1. 写入新的标题行
            writer.writerow(new_header)

            # 标记是否已跳过所有不需要的初始行
            header_found = False

            for row_number, row in enumerate(reader, start=1):
                # 将每一行视为一个列表,row_number 从 1 开始

                # 检查是否已找到有效数据行(即非空或非分隔线)
                # 这里的逻辑是:如果行的字段数量小于等于1,则跳过
                # 这可以有效跳过空行和只有分隔符的行(如 "-------------------")
                if len(row) <= 1:
                    continue # 跳过当前行,不写入输出文件

                # 假设第一行有效数据是旧的标题行,我们需要跳过它
                # 更通用的方法是检查行的内容,例如判断是否包含预期的数据类型
                # 这里我们假设在跳过空行和分隔线后,第一行非空数据是旧的标题
                if not header_found:
                    # 尝试更智能地识别数据行,例如检查最后一个字段是否可以转换为浮点数
                    # 如果不能,则可能是标题或无效行,继续跳过
                    try:
                        # 假设数据行的最后一个字段是数字
                        _ = float(row[-1])
                        header_found = True # 确认找到数据行
                    except (ValueError, IndexError):
                        continue # 不是有效数据行,跳过

                # 确保我们已经跳过了所有初始的无效行和旧的标题行
                if header_found:
                    # 4. 遍历当前行的每个字段,将连字符 '-' 替换为分号 ';'
                    # 使用列表推导式高效地创建新行
                    new_row = [field.replace('-', ';') for field in row]
                    # 写入处理后的行
                    writer.writerow(new_row)

        print(f"文件 '{input_filepath}' 已成功处理并保存到 '{output_filepath}'")

    except FileNotFoundError:
        print(f"错误:文件 '{input_filepath}' 未找到。")
    except Exception as e:
        print(f"处理文件时发生错误:{e}")

# 定义输入和输出文件路径
input_file = 'input.csv'
output_file = 'output.csv'

# 定义新的标题行
custom_header = ['Column1', 'Column2', 'Column3', 'Column4', 'Column5', 'Column6', 'Column7', 'Column8']

# 调用函数进行处理
process_csv_file(input_file, output_file, custom_header)

3. 代码解析

  1. 文件打开与编码处理:

    • with open(input_filepath, 'r', encoding="utf-16") as read_file, ...: 使用with语句同时打开输入和输出文件,确保文件句柄在操作结束后自动关闭。输入文件指定utf-16编码,输出文件指定utf-8编码。
    • newline='':对于csv.writer,这是一个非常重要的参数,它能防止在Windows系统上写入文件时出现额外的空行。
  2. CSV读取器与写入器:

    • reader = csv.reader(read_file, delimiter=","): 创建csv.reader对象,告诉它输入文件使用逗号作为分隔符。
    • writer = csv.writer(write_file, delimiter=";"): 创建csv.writer对象,告诉它输出文件使用分号作为新的分隔符。
  3. 写入新标题:

    • writer.writerow(new_header): 在处理任何数据之前,将预定义的新标题行写入输出文件。
  4. 跳过无效行:

    • if len(row)
    • if not header_found: 块:这是一个更智能的跳过机制,旨在识别并跳过旧的标题行。它尝试将行的最后一个字段转换为浮点数。如果成功,则认为这是有效的数据行,并设置header_found = True;如果失败(ValueError或IndexError,后者处理空行或只有一个字段的行),则认为它不是数据行(可能是旧标题或无效行),继续跳过。这种方法比硬编码行号更具弹性。
  5. 替换字段中的连字符:

    • new_row = [field.replace('-', ';') for field in row]: 这是一个列表推导式,它遍历当前行row中的每一个字段(字符串),对每个字段调用replace('-', ';')方法,将其中的连字符替换为分号,然后将所有处理后的字段组成一个新的列表new_row。
    • writer.writerow(new_row): 将处理后的行写入输出文件。
  6. 错误处理:

    • try...except块用于捕获可能发生的FileNotFoundError或其他潜在的Exception,增强程序的健壮性。

最佳实践与注意事项

  • 资源管理: 始终使用with open(...)语句来处理文件,以确保文件在操作完成后被正确关闭,避免资源泄露和ValueError: I/O operation on closed file.错误。
  • 逐行处理: 对于大型文件,逐行读取和写入数据是更高效和内存友好的方法,避免一次性将整个文件加载到内存中。
  • csv模块的正确使用: 理解csv.reader和csv.writer的delimiter和newline=''参数至关重要。newline=''对于csv.writer尤其重要,可以避免在Windows上写入额外的空行。
  • 数据验证与跳过逻辑: 根据实际数据特征设计跳过无效行的逻辑。len(row)是一个简单有效的方法,而结合try-except进行数据类型转换验证(如float(row[-1]))则能更精确地识别数据行。
  • 编码问题: 务必明确输入和输出文件的编码格式,并在open()函数中正确指定encoding参数。常见的编码包括utf-8、utf-16、gbk等。
  • 字符串与列表操作: 明确split()和replace()是字符串方法。如果要对列表中的每个字符串元素进行操作,需要遍历列表并对每个元素单独调用这些方法,如本例中的列表推导式。

总结

通过本教程,我们学习了如何使用Python的csv模块和文件I/O操作,有效地清洗和转换结构不规范的CSV文件。我们不仅解决了删除特定行、更改分隔符、替换字符和转换编码等具体问题,还深入探讨了ValueError: I/O operation on closed file.和AttributeError: 'list' object has no attribute 'split'这两个常见错误的根源及规避方法。掌握这些技巧将使您能够更自信、更高效地处理实际数据清洗任务。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

765

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

639

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

764

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

619

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1285

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

549

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

709

2023.08.11

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 6万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号