第13章-csv模块

csv模块使python程序员能够解析csv(逗号分隔值)文件。csv文件是一个人类可读的文本文件,其中每行有许多字段,用逗号或其他分隔符分隔。您可以将每一行看作一行,每个字段看作一列。csv格式没有标准,但它们非常相似,以至于csv模块能够读取绝大多数csv文件。也可以使用csv模块写入csv文件。

读取csv文件

有两种方法可以读取csv文件。您可以使用csv模块 读者 或者您可以使用 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, "r") as f_obj:
        csv_reader(f_obj)

让我们花点时间把这件事讲清楚。首先,我们必须实际导入 csv 模块。然后我们创建一个非常简单的函数 csv_reader 接受文件对象。在函数内部,我们将文件对象传递到 csv.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 .现在我们准备使用dictleader类解析文件。让我们试试看:

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类。我们告诉听写器分隔符是逗号。这实际上不是必需的,因为没有这个关键字参数代码仍然可以工作。不过,最好是直截了当,这样你就知道这里发生了什么。接下来,我们循环访问reader对象,发现reader对象中的每一行都是一个字典。这使得打印特定的行非常容易。

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

写入csv文件

csv模块还有两种方法,您可以用来编写csv文件。您可以使用 作家 函数或DictWriter类。我们也要看看这两个。我们将担任编剧一职。让我们来看一个简单的例子:

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)

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对象。然后我们循环遍历嵌套的列表结构,并将每一行写到磁盘上。注意,我们在创建编写器对象时指定了分隔符应该是什么。如果您希望分隔符是除逗号之外的其他内容,那么您可以在这里设置它。

现在我们准备学习如何使用 DictWriter 上课!我们将使用以前版本的数据,并将其转换为字典列表,我们可以将这些字典提供给饥饿的听写者。让我们看看:

import csv

def csv_dict_writer(path, fieldnames, data):
    """
    Writes a CSV file using DictWriter
    """
    with open(path, "w", newline='') 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)

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

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':'Stiedmannberg'、'First_name':'Dedric'、'Last_name':'Medhurst']

在第二次会议结束时,我们将 csv_dict_writer 函数并传入所有必需的参数。在函数内部,我们创建一个dictwriter实例,并将文件对象、分隔符值和字段名列表传递给它。接下来,我们将字段名写入磁盘,并一次循环一行数据,将数据写入磁盘。dictwriter类还支持 写入行 方法,而不是循环。这个 csv.writer 函数还支持此功能。

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

总结

现在您知道了如何使用csv模块读取和写入csv文件。有许多网站以这种格式发布数据,在商业世界中被大量使用。在下一章中,我们将开始学习ConfigParser模块。