Skip to content

Python CSV 模块:读写 CSV 文件详解

CSV (Comma Separated Values,逗号分隔值) 是一种非常常见的数据存储和交换格式。 它以纯文本形式存储表格数据(数字和文本),易于阅读和处理,并且可以被各种软件程序支持。

CSV 文件的核心特点是:

  • 分隔符: 使用特定的字符(例如逗号,)分隔每个字段。
  • 行: 每一行代表一条数据记录。
  • 字段: 每条记录包含多个字段。
  • 可选标题行: 第一行通常是标题行,用于描述每个字段的含义。
  • 引号处理: 如果字段中包含分隔符或特殊字符,则需要使用引号(通常是双引号")将该字段括起来。

例如,一个简单的 CSV 文件可能如下所示:

csv
Name,Age,City
Alice,30,New York
Bob,25,London
Charlie,35,Paris

在这个例子中,逗号,是分隔符,第一行是标题行,后面每一行代表一个人的姓名、年龄和城市信息。

Python 提供了一个内置的 csv 模块,专门用于处理 CSV 文件的读取和写入操作。 这个模块使得处理 CSV 数据变得非常简单方便。

1. 为什么要使用 CSV 模块?

虽然你可以使用字符串操作来手动解析 CSV 文件,但是 csv 模块提供了以下优势:

  • 简化代码: 它封装了 CSV 文件的解析逻辑,使你无需编写复杂的字符串处理代码。
  • 处理引号和转义: 它可以正确处理包含引号和转义字符的字段。
  • 支持多种分隔符: 它允许你指定不同的分隔符和引号字符,以适应不同的 CSV 文件格式。
  • 自动类型转换: 虽然 csv 模块返回的是字符串,但你可以方便地将这些字符串转换为其他数据类型(例如整数、浮点数)。

2. 读取 CSV 文件

csv.reader() 函数是读取 CSV 文件的核心。 它接受一个文件对象作为输入,并返回一个 reader 对象,你可以使用该对象逐行迭代 CSV 文件。

2.1 csv.reader() 函数的参数

csv.reader(csvfile, delimiter=',', quotechar='"', **fmtparams)

  • csvfile: 一个可迭代的对象,通常是一个打开的文本文件对象。 重要: 打开文件时,建议使用 newline='' 参数,以避免由于不同平台的换行符差异而导致的问题。
  • delimiter: 用于分隔字段的字符,默认为逗号,
  • quotechar: 用于包围包含分隔符的字段的字符,默认为双引号"
  • **fmtparams: 其他可选的格式化参数,例如 skipinitialspace(忽略分隔符后的空格)和 strict(在遇到错误的 CSV 行时引发异常)。

2.2 示例:读取简单的 CSV 文件

假设我们有一个名为 students.csv 的文件,内容如下:

csv
Name,Major,GPA
Alice,Computer Science,3.8
Bob,Engineering,3.5
Charlie,Mathematics,3.9

以下代码演示如何使用 csv.reader() 读取该文件:

python
import csv

try:
    with open('students.csv', 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            print(row)
except FileNotFoundError:
    print("文件 'students.csv' 未找到。")
except Exception as e:
    print(f"读取 CSV 时出错: {e}")

代码解释:

  1. import csv: 导入 csv 模块。
  2. with open('students.csv', 'r', newline='', encoding='utf-8') as csvfile:: 使用 with 语句打开文件,确保文件在使用后自动关闭。 'r' 表示以只读模式打开文件。 newline='' 防止出现换行符问题。 encoding='utf-8' 指定文件编码为 UTF-8,可以正确处理包含中文等非 ASCII 字符的文件。
  3. reader = csv.reader(csvfile): 创建一个 reader 对象,用于读取 CSV 文件。
  4. for row in reader:: 迭代 reader 对象,每次迭代返回一行数据,以列表的形式存储在 row 变量中。
  5. print(row): 打印每一行数据。

输出:

['Name', 'Major', 'GPA']
['Alice', 'Computer Science', '3.8']
['Bob', 'Engineering', '3.5']
['Charlie', 'Mathematics', '3.9']

2.3 跳过标题行

通常,CSV 文件的第一行是标题行。 如果你不想处理标题行,可以使用 next() 函数跳过它:

python
import csv

try:
    with open('students.csv', 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        header = next(reader)  # 读取并跳过标题行
        print("标题:", header)
        for row in reader:
            print(row)
except FileNotFoundError:
    print("文件 'students.csv' 未找到。")
except Exception as e:
    print(f"读取 CSV 时出错: {e}")

输出:

标题: ['Name', 'Major', 'GPA']
['Alice', 'Computer Science', '3.8']
['Bob', 'Engineering', '3.5']
['Charlie', 'Mathematics', 3.9']

2.4 使用不同的分隔符和引号字符

如果你的 CSV 文件使用不同的分隔符或引号字符,你可以在 csv.reader() 函数中指定它们。 例如,如果你的 CSV 文件使用分号;作为分隔符,并且使用尖括号<>作为引号字符,你可以这样读取它:

python
import csv

try:
    with open('data.csv', 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile, delimiter=';', quotechar='<')
        for row in reader:
            print(row)
except FileNotFoundError:
    print("文件 'data.csv' 未找到。")
except Exception as e:
    print(f"读取 CSV 时出错: {e}")

假设 data.csv 包含以下内容:

csv
Name;Address;Phone
John;<123 Main St; Anytown>;555-1234
Jane;<456 Oak Ave; Somecity>;555-5678

输出将会是:

['Name', 'Address', 'Phone']
['John', '123 Main St; Anytown', '555-1234']
['Jane', '456 Oak Ave; Somecity', '555-5678']

3. 写入 CSV 文件

csv.writer() 函数用于创建 writer 对象,你可以使用该对象将数据写入 CSV 文件。

3.1 csv.writer() 函数的参数

csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL, **fmtparams)

  • csvfile: 一个可迭代的对象,通常是一个打开的文本文件对象。 重要: 打开文件时,建议使用 newline='' 参数。
  • delimiter: 用于分隔字段的字符,默认为逗号,
  • quotechar: 用于包围包含分隔符的字段的字符,默认为双引号"
  • quoting: 一个控制何时使用引号的常量。 常用的值包括:
    • csv.QUOTE_ALL: 所有字段都用引号括起来。
    • csv.QUOTE_MINIMAL: 仅在字段包含分隔符、引号字符或特殊字符时才使用引号。 这是默认值。
    • csv.QUOTE_NONNUMERIC: 所有非数字字段都用引号括起来。
    • csv.QUOTE_NONE: 永远不使用引号。 如果字段中包含分隔符,写入时会引发错误。
  • **fmtparams: 其他可选的格式化参数。

3.2 写入数据

csv.writer 对象提供了以下两个主要方法来写入数据:

  • writerow(row): 将一行数据写入 CSV 文件。 row 必须是一个可迭代的对象(例如列表或元组)。
  • writerows(rows): 将多行数据写入 CSV 文件。 rows 必须是一个可迭代的对象,其中每个元素都是一行数据。

3.3 示例:写入 CSV 文件

以下代码演示如何使用 csv.writer() 创建一个包含学生信息的 CSV 文件:

python
import csv

header = ['Name', 'Major', 'GPA']
data = [
    ['Alice', 'Computer Science', 3.8],
    ['Bob', 'Engineering', 3.5],
    ['Charlie', 'Mathematics', 3.9]
]

try:
    with open('students_output.csv', 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)

        # 写入标题行
        writer.writerow(header)

        # 写入数据行
        writer.writerows(data)

    print("文件 'students_output.csv' 写入成功。")
except IOError as e:
    print(f"写入 CSV 时出错: {e}")

代码解释:

  1. import csv: 导入 csv 模块。
  2. header = ['Name', 'Major', 'GPA']: 定义标题行。
  3. data = [...]: 定义数据行。
  4. with open('students_output.csv', 'w', newline='', encoding='utf-8') as csvfile:: 以写入模式'w'打开文件。 如果文件不存在,则创建该文件。 如果文件已存在,则覆盖该文件。
  5. writer = csv.writer(csvfile): 创建一个 writer 对象。
  6. writer.writerow(header): 写入标题行。
  7. writer.writerows(data): 写入数据行。

输出(students_output.csv):

csv
Name,Major,GPA
Alice,Computer Science,3.8
Bob,Engineering,3.5
Charlie,Mathematics,3.9

3.4 使用不同的分隔符和引号

python
import csv

header = ['Name', 'Address', 'Phone']
data = [
    ['John', '123 Main St; Anytown', '555-1234'],
    ['Jane', '456 Oak Ave; Somecity', '555-5678']
]

try:
    with open('contacts.csv', 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile, delimiter=';', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        writer.writerow(header)
        writer.writerows(data)
    print("文件 'contacts.csv' 写入成功。")
except IOError as e:
    print(f"写入 CSV 时出错: {e}")

在这个例子中,分隔符设置为;,引号字符设置为"quoting=csv.QUOTE_MINIMAL 确保只有包含分隔符的字段才会被引号括起来。

输出 (contacts.csv):

csv
Name;Address;Phone
John;"123 Main St; Anytown";555-1234
Jane;"456 Oak Ave; Somecity";555-5678

4. csv.DictReadercsv.DictWriter

除了 csv.readercsv.writer 之外,csv 模块还提供了 csv.DictReadercsv.DictWriter 类,它们可以将 CSV 文件中的每一行数据转换为字典,从而更方便地访问数据。

4.1 csv.DictReader

csv.DictReader 的工作方式与 csv.reader 类似,但它将每一行数据转换为一个字典,其中字典的键是标题行中的字段名。

python
import csv

try:
    with open('students.csv', 'r', newline='', encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            print(row['Name'], row['Major'], row['GPA'])
except FileNotFoundError:
    print("文件 'students.csv' 未找到。")
except Exception as e:
    print(f"读取 CSV 时出错: {e}")

输出:

Alice Computer Science 3.8
Bob Engineering 3.5
Charlie Mathematics 3.9

4.2 csv.DictWriter

csv.DictWriter 的工作方式与 csv.writer 类似,但它接受字典形式的数据作为输入,并将其写入 CSV 文件。

python
import csv

header = ['Name', 'Major', 'GPA']
data = [
    {'Name': 'Alice', 'Major': 'Computer Science', 'GPA': 3.8},
    {'Name': 'Bob', 'Major': 'Engineering', 'GPA': 3.5},
    {'Name': 'Charlie', 'Major': 'Mathematics', 'GPA': 3.9}
]

try:
    with open('students_dict_output.csv', 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=header)

        # 写入标题行
        writer.writeheader()

        # 写入数据行
        writer.writerows(data)

    print("文件 'students_dict_output.csv' 写入成功。")
except IOError as e:
    print(f"写入 CSV 时出错: {e}")

代码解释:

  1. csv.DictWriter(csvfile, fieldnames=header): 创建 DictWriter 对象,并指定字段名 fieldnamesfieldnames 必须是一个包含所有字段名的列表。
  2. writer.writeheader(): 写入标题行。 此方法使用 fieldnames 中的字段名作为标题。
  3. writer.writerows(data): 写入数据行。 data 必须是一个字典列表,其中每个字典都包含与 fieldnames 中字段名相对应的数据。

输出(students_dict_output.csv):

csv
Name,Major,GPA
Alice,Computer Science,3.8
Bob,Engineering,3.5
Charlie,Mathematics,3.9

csv 模块是 Python 中处理 CSV 文件的强大工具。 它提供了简单易用的 API,可以方便地读取和写入 CSV 数据。 通过使用 csv.readercsv.writercsv.DictReadercsv.DictWriter,你可以轻松地处理各种 CSV 文件格式,并将 CSV 数据集成到你的 Python 应用程序中。 记住始终使用 newline='' 打开文件,并根据需要指定分隔符、引号字符和编码方式,以确保你的代码能够正确处理各种 CSV 文件。