geekdoc-python-zh/docs/pythonlibrary/python-101-reading-and-writ...

9.8 KiB
Raw Blame History

Python 101:读取和写入 CSV 文件

原文:https://www.blog.pythonlibrary.org/2014/02/26/python-101-reading-and-writing-csv-files/

Python 有一个庞大的模块库包含在它的发行版中。csv 模块为 Python 程序员提供了解析 CSV(逗号分隔值)文件的能力。CSV 文件是人类可读的文本文件其中每一行都有许多由逗号或其他分隔符分隔的字段。您可以将每行视为一行将每个字段视为一列。csv 格式没有标准但是它们非常相似CSV 模块能够读取绝大多数 CSV 文件。您也可以使用 csv 模块编写 CSV 文件。


读取 CSV 文件

有两种方法可以读取 CSV 文件。你可以使用 csv 模块的 reader 函数或者你可以使用 DictReader 类。我们将研究这两种方法。但是首先,我们需要得到一个 CSV 文件,这样我们就有东西可以解析了。有许多网站以 CSV 格式提供有趣的信息。我们将使用世界卫生组织(世卫组织)的网站下载一些关于结核病的信息。可以去这里领取:【http://www.who.int/tb/country/data/download/en/。一旦你拿到文件,我们就可以开始了。准备好了吗?然后我们来看一些代码!


import csv

#----------------------------------------------------------------------
def csv_reader(file_obj):
    """
    Read a csv file
    """
    reader = csv.reader(file_obj)
    for row in reader:
        print(" ".join(row))

#----------------------------------------------------------------------
if __name__ == "__main__":
    csv_path = "TB_data_dictionary_2014-02-26.csv"
    with open(csv_path, "rb") as f_obj:
        csv_reader(f_obj)

让我们花点时间来分解一下。首先,我们必须实际导入 csv 模块。然后我们创建一个非常简单的函数,名为 csv_reader ,它接受一个文件对象。在函数内部,我们将文件对象传递给 csv_reader 函数,该函数返回一个 reader 对象。reader 对象允许迭代,就像常规的 file 对象一样。这让我们遍历 reader 对象中的每一行,并打印出数据行,去掉逗号。这是因为每一行都是一个列表,我们可以将列表中的每个元素连接在一起,形成一个长字符串。

现在让我们创建自己的 CSV 文件,并将其输入到 DictReader 类中。这里有一个非常简单的问题:


first_name,last_name,address,city,state,zip_code
Tyrese,Hirthe,1404 Turner Ville,Strackeport,NY,19106-8813
Jules,Dicki,2410 Estella Cape Suite 061,Lake Nickolasville,ME,00621-7435
Dedric,Medhurst,6912 Dayna Shoal,Stiedemannberg,SC,43259-2273

让我们将它保存在一个名为 data.csv 的文件中。现在我们准备使用 DictReader 类解析文件。让我们试一试:


import csv

#----------------------------------------------------------------------
def csv_dict_reader(file_obj):
    """
    Read a CSV file using csv.DictReader
    """
    reader = csv.DictReader(file_obj, delimiter=',')
    for line in reader:
        print(line["first_name"]),
        print(line["last_name"])

#----------------------------------------------------------------------
if __name__ == "__main__":
    with open("data.csv") as f_obj:
        csv_dict_reader(f_obj)

在上面的例子中,我们打开一个文件,并像以前一样将文件对象传递给我们的函数。该函数将文件对象传递给我们的 DictReader 类。我们告诉 DictReader 分隔符是逗号。这实际上并不是必需的,因为没有那个关键字参数,代码仍然可以工作。然而,明确一点是个好主意,这样你就知道这里发生了什么。接下来我们遍历 reader 对象,发现 reader 对象中的每一行都是一个字典。这使得打印出该行的特定部分非常容易。

现在我们准备学习如何将 csv 文件写入磁盘。


编写 CSV 文件

csv 模块也有两种方法可以用来编写 CSV 文件。你可以使用 writer 函数或者 DictWriter 类。我们也将研究这两个问题。我们将从 writer 函数开始。让我们看一个简单的例子:


# Python 2.x version
import csv

#----------------------------------------------------------------------
def csv_writer(data, path):
    """
    Write data to a CSV file path
    """
    with open(path, "wb") as csv_file:
        writer = csv.writer(csv_file, delimiter=',')
        for line in data:
            writer.writerow(line)

#----------------------------------------------------------------------
if __name__ == "__main__":
    data = ["first_name,last_name,city".split(","),
            "Tyrese,Hirthe,Strackeport".split(","),
            "Jules,Dicki,Lake Nickolasville".split(","),
            "Dedric,Medhurst,Stiedemannberg".split(",")
            ]
    path = "output.csv"
    csv_writer(data, path)

在上面的代码中,我们创建了一个接受两个参数的 csv_writer 函数:数据和路径。数据是我们在脚本底部创建的列表列表。我们使用前一个例子中数据的简化版本,并在逗号上分割字符串。这将返回一个列表。所以我们最终得到一个嵌套列表,如下所示:


[['first_name', 'last_name', 'city'],
 ['Tyrese', 'Hirthe', 'Strackeport'],
 ['Jules', 'Dicki', 'Lake Nickolasville'],
 ['Dedric', 'Medhurst', 'Stiedemannberg']]

csv_writer 函数打开我们传入的路径,并创建一个 csv writer 对象。然后我们遍历嵌套列表结构,将每一行写到磁盘上。注意,我们在创建 writer 对象时指定了分隔符应该是什么。如果您希望分隔符不是逗号,那么您可以在这里设置它。

现在如果你想用 Python 3 写一个 csv 文件,语法略有不同。下面是您必须重写该函数的方式:


# Python 3.x version
import csv

def csv_writer(data, path):
    """
    Write data to a CSV file path
    """
    with open(path, "w", newline='') as csv_file:
        writer = csv.writer(csv_file, delimiter=',')
        for line in data:
            writer.writerow(line)

您会注意到,您需要将写模式更改为仅仅是**w,并添加换行符**参数。

现在我们准备学习如何使用 DictWriter 类编写 CSV 文件!我们将使用前一个版本的数据,并将其转换成一个字典列表,我们可以将它提供给我们饥渴的 DictWriter。让我们来看看:


# Python 2.x version
import csv

#----------------------------------------------------------------------
def csv_dict_writer(path, fieldnames, data):
    """
    Writes a CSV file using DictWriter
    """
    with open(path, "wb") as out_file:
        writer = csv.DictWriter(out_file, delimiter=',', fieldnames=fieldnames)
        writer.writeheader()
        for row in data:
            writer.writerow(row)

#----------------------------------------------------------------------
if __name__ == "__main__":
    data = ["first_name,last_name,city".split(","),
            "Tyrese,Hirthe,Strackeport".split(","),
            "Jules,Dicki,Lake Nickolasville".split(","),
            "Dedric,Medhurst,Stiedemannberg".split(",")
            ]
    my_list = []
    fieldnames = data[0]
    for values in data[1:]:
        inner_dict = dict(zip(fieldnames, values))
        my_list.append(inner_dict)

    path = "dict_output.csv"
    csv_dict_writer(path, fieldnames, my_list)

注意:要将这段代码转换成 Python 3 语法,您需要像以前一样用语句修改*:用 open(path" w "newline= ' ')作为 out_file:***

我们将首先从第二部分开始。如你所见,我们从之前的嵌套列表结构开始。接下来,我们创建一个空列表和一个包含字段名称的列表,这恰好是嵌套列表中的第一个列表。记住,列表是从零开始的,所以列表中的第一个元素从零开始!接下来,我们遍历嵌套列表结构,从第二个元素开始:


for values in data[1:]:
    inner_dict = dict(zip(fieldnames, values))
    my_list.append(inner_dict)

for 循环中,我们使用 Python 内置函数来创建字典。zip方法将接受两个迭代器(本例中是列表),并将它们转换成元组列表。这里有一个例子:


zip(fieldnames, values)
[('first_name', 'Dedric'), ('last_name', 'Medhurst'), ('city', 'Stiedemannberg')]

现在,当您在dict中包装该调用时,它会将元组列表转换为字典。最后,我们把字典添加到列表中。当for完成时,您将得到如下所示的数据结构:


[{'city': 'Strackeport', 'first_name': 'Tyrese', 'last_name': 'Hirthe'},
{'city': 'Lake Nickolasville', 'first_name': 'Jules', 'last_name': 'Dicki'},
{'city': 'Stiedemannberg', 'first_name': 'Dedric', 'last_name': 'Medhurst'}]

在第二个会话结束时,我们调用我们的 csv_dict_writer 函数,并传入所有需要的参数。在函数内部,我们创建一个 DictWriter 实例并向它传递一个文件对象、一个分隔符值和我们的字段名列表。接下来我们将字段名写到磁盘上一次循环一行数据将数据写到磁盘上。DictWriter 类也支持 writerows 方法,我们可以用它来代替循环。 csv.writer 函数也支持该功能。

您可能有兴趣知道,您还可以使用 csv 模块创建方言。这允许您以非常明确的方式告诉 csv 模块如何读取或写入文件。如果您因为来自客户端的格式奇怪的文件而需要这种东西,那么您会发现这种功能非常有价值。


包扎

现在您知道了如何使用 csv 模块来读写 CSV 文件。有许多网站以这种格式发布数据,这种格式在商业领域被广泛使用。开心快乐编码!


附加阅读

  • Python 文档- 第 13.1 节 csv
  • 用 Python DictReader 和 DictWriter 读写 CSV 文件
  • 本周 Python 模块: csv