python csv库使用教程

  • Post author:
  • Post category:python




前言

CSV,Comma-Separated Values,中文名为逗号分隔值,其文件以纯文本形式存储表格数据(数字和文本)。CSV是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。csv文件可以用excel或者记事本打开。

Python内置了专用于处理csv文件的库,名为:csv。这个库不用

pip install

,直接

import

就好。关于csv库使用最好的教程其实就是官网

csv教程

,不过官网的教程过于晦涩难懂,对新手及其不友好。英文版的文档虽然详细准确但是大多数小伙伴的英语可能并不好,中文版的文档由于翻译的原因又不太“原汁原味”,歧义较多。本教程是我在阅读完官方文档后,并参考其他文章,最后整理出的教程,希望能给想学csv库使用的小伙伴一个参考。



csv库概览

csv 库常用的对象:


  • csv.reader

    :从csv文件读取数据,返回list

  • csv.writer

    :往csv文件写入数据,需要传入list

  • csv.DictReader

    :从csv文件读取数据,返回dict

  • csv.DictWriter

    :往csv文件写入数据,需要传入dict

  • csv.Dialect

    :指定csv文件的解析格式,可以利用它自定义csv格式



读取数据



csv.reader

reader(csvfile, dialect='excel', **fmtparams)

下面是我用vscode写代码时,悬浮窗给的提示,感觉比官网的详细。

vscode上显示的reader参数

参数说明:


  • csvfile

    ,必须是支持迭代(

    Iterator

    )的对象,可以是文件(

    file

    )对象或者列表(list)对象,如果是文件对象,打开时需要指定

    newline=''

    (但是实际上不指定似乎也没影响,只有写入时才需要指定,不过官方文档建议,为了安全,还是指定比较好)。

  • dialect

    ,编码风格,默认为excel的风格,也就是用逗号

    ,

    分隔,

    dialect

    方式也支持自定义,通过调用

    register_dialect

    方法来注册,下文会提到。

  • delimiter

    :

    str = ","

    ,内容分隔符,默认是英文逗号。

  • quotechar

    :指定引用使用到的字符,这个参数似乎跟quoting一起使用。

  • escapechar

    :转义字符,对于writer,在 quoting 设置为 QUOTE_NONE 的情况下转义delimiter(定界符),在 doublequote 设置为 False 的情况下转义 quotechar。对于reader,去除其后所跟字符的任何特殊含义。

  • quoting

    :指定引用方式。该属性可以等于任何 QUOTE_* 常量,

    从csv文件读取的每一行数据都会以list的形式返回,这个list的元素都是string。csv库不会自动识别数字,除非指定quoting= QUOTE_NONNUMERIC。

从csv文件读取的每一行数据都会以

list

的形式返回,这个list的元素都是

string

。csv库不会自动识别数字,除非指定

quoting= QUOTE_NONNUMERIC

示例:

csv原文件:

在这里插入图片描述

with open(filename,"r",encoding="utf-8") as file1:
    reader=csv.reader(file1)
    header=next(reader)
    # 获取标题
    title1=header[0]
    title2=header[1]
    title3=header[2]
    
    for row in reader:
        # row是一个列表,csv文件中以逗号分割的数据就是列表的每个元素
        print("{}:{},{}:{},{}:{}".format(title1,row[0],
        title2,row[1],title3,row[2]))

输出:

在这里插入图片描述

注意,使用

withopen

打开文件的时候,编码方式会默认采用系统默认的编码(很多情况下是

gbk

),所以为了不出错还是指定

utf-8

比较好。

看另一个例子:

在这里插入图片描述

with open('test.csv','r',encoding='utf-8',newline='') as f:
   reader=csv.reader(f,quotechar="|",quoting=csv.QUOTE_NONNUMERIC)
   for row in reader:
       print(row)

输出:

['a', 1.0]
['b', 2.0]
['c', 3.0]
['d', 4.0]

可见指定

quotechar



quoting

后,没有被引用的数组数据都被转化成了

float

,而被引用的数据都去除了

quotechar



quotechar

夹着的内容也是

string



补充:官网定义的一些常量:

csv 模块定义了以下常量:


  • csv.QUOTE_ALL


    指示 writer 对象给所有字段加上引号。

  • csv.QUOTE_MINIMAL


    指示 writer 对象仅为包含特殊字符(例如 定界符、引号字符 或 行结束符 中的任何字符)的字段加上引号。

  • csv.QUOTE_NONNUMERIC


    指示 writer 对象为所有非数字字段加上引号。

    指示 reader 将所有未用引号引出的字段转换为 float 类型。

  • csv.QUOTE_NONE


    指示 writer 对象不使用引号引出字段。当 定界符 出现在输出数据中时,其前面应该有 转义符。如果未设置 转义符,则遇到任何需要转义的字符时,writer 都会抛出 Error 异常。

    指示 reader 不对引号字符进行特殊处理。



csv.DictReader

class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

参数详解:

在这里插入图片描述

在这里插入图片描述



csv.reader

一样读取数据,但是会把每行映射到一个dict,dict的键由

fieldnames

指定。


  • fieldnames

    :字典的键,其实就是表格的header,必须是一个

    Sequence

    ,如果忽略,文件的第一行会被当做header。

  • restkey

    :如果header的个数小于data的列数,每行剩余列的data会被放入一个list中,键会被指定为

    restkey

    (default

    None


  • restval

    : 若header的个数大于数据列数,则缺失值都会被填充为

    restval

    (default

    None

    )。

    不管是

    csv.reader

    还是

    csv.DictReader

    ,都有一个

    __next__()

    方法,将下一行内容用

    Dialect

    解析后,以list或者dict的形式返回。

示例:

csv原文件:

在这里插入图片描述

with open(filename,"r",encoding="utf-8") as file1:
    reader=csv.DictReader(file1)
    for row in reader:
        # row是一个字典
        print(row)

结果:

在这里插入图片描述

默认把第一行作为标题了。

另一个示例:

在这里插入图片描述


with open('named csv.csv','r',encoding='utf-8',newline='') as file3:
   dictreader=csv.DictReader(file3)
   for row in dictreader:
       print(row)

输出:

{'身高': '170', '体重': '60', '年龄': '20', None: ['1', '1']}
{'身高': '175', '体重': '65', '年龄': '25', None: ['2', '2']}
{'身高': '180', '体重': '70', '年龄': '30', None: ['3', '3']}



写入数据



csv.writer

writer(csvfile, dialect=‘excel’, **fmtparams)

参数详解:

在这里插入图片描述


  • csvfile

    可以是任意一个定义了write方法的对象。

  • delimiter

    :指定分隔符,默认是英文逗号。

    值得注意的是,在写入时一定要指定

    newline=''

    ,否则写入时每两行之间都会多出一个空行。

    其他参数跟reader一样。

    示例:
with open(filename,"w",encoding="utf-8",newline="") as file1:
    # 以写方式打开文件。注意添加 newline="",否则会在两行数据之间都插入一行空白。
    writer=csv.writer(file1)
    headers=["姓名","性别","年龄"]
    data=[["张三","男","20"],["王五","男","18"]]
    writer.writerow(headers)
    # 方式一
    writer.writerows(data)
    # 方式二
    # for row in data:
    #     writer.writerow(row)

结果:

在这里插入图片描述



csv.DictWriter

class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

参数详解:

在这里插入图片描述

在这里插入图片描述


  • fieldnames

    就是需要传入的列名,这些列名需要作为DictWriter的writerow方法传入的字典的键。

  • restval

    如果传入的字典缺失了某些键,则缺失值会用

    restval

    填充。

  • extrasaction

    如果传入的字典多了一些键不在fieldnames里面,

    extrasaction

    就派上用场了。默认为

    'raise'

    ,即

    raise ValueError

    。若为

    'ignore'

    ,则直接忽略多余的键值对。

注意,

DictReader



fieldnames

是可选的,如果不传入,就默认以第一行作为

fieldnames

,但是

DictWrite

r的

fieldnames

参数是必须的。

示例:

with open(filename,"w",encoding="utf-8",newline="") as file1:
    # 以写方式打开文件。注意添加 newline="",否则会在两行数据之间都插入一行空白。
    headers=["姓名","性别","年龄"]
    # 即使打乱键的顺序,写入也不会出错
    data=[{"年龄":"20","性别":"男","姓名":"张三"},{"姓名":"王五","性别":"男","年龄":"18"}]
    # 将header作为参数传入
    writer=csv.DictWriter(file1,headers)
    writer.writeheader()
    # # 方式一
    # writer.writerows(data)
    # 方式二
    for row in data:
        writer.writerow(row)

结果:

在这里插入图片描述

总结writer的方法:


  • csvwriter.writerow(row)


    将 row 形参(被dialect格式化后)写入到 writer 的文件对象中,一次写入一行。

  • csvwriter.writerows(rows)


    rows是一个以上述row作为元素的迭代器。一次写入多行。



其他内容



使用Dialect自定义csv格式

class csv.Dialect

Dialect 类是一个容器类,其属性包含有如何处理双引号、空白符、分隔符等的信息。 由于缺少严格的 CSV 规格描述,不同的应用程序会产生略有差别的 CSV 数据。 Dialect 实例定义了 reader 和 writer 实例将具有怎样的行为。

借助Dialect类,我们可以自定义csv文件格式,即我们的文件可以不是标准的csv格式,但是使用csv库也可以读取、写入文件内容。关于所有定义好的dialect,他们的名字可以使用

csv.list_dialects()

函数获取。

Dialect 类支持以下属性:


  • Dialect.delimiter


    一个用于分隔字段的单字符,默认为

    ','


  • Dialect.doublequote


    控制出现在字段中的 引号字符 本身应如何被引出。当该属性为 True 时,双写引号字符。如果该属性为 False,则在 引号字符 的前面放置 转义符。默认值为 True。

    在输出时,如果 doublequote 是 False,且 转义符 未指定,且在字段中发现 引号字符 时,会抛出 Error 异常。


  • Dialect.escapechar


    一个用于 writer 的单字符,用来在 quoting 设置为 QUOTE_NONE 的情况下转义 定界符,在 doublequote 设置为 False 的情况下转义 引号字符。在读取时,escapechar 去除了其后所跟字符的任何特殊含义。该属性默认为 None,表示禁用转义。


  • Dialect.lineterminator


    放在 writer 产生的行的结尾,默认为

    '\r\n'



    备注 reader 经过硬编码,会识别 ‘\r’ 或 ‘\n’ 作为行尾,并忽略

    lineterminator


  • Dialect.quotechar


    一个单字符,用于包住含有特殊字符的字段,特殊字符如 定界符 或 引号字符 或换行符。默认为 ‘”’。


  • Dialect.quoting


    控制 writer 何时生成引号,以及 reader 何时识别引号。该属性可以等于任何

    QUOTE_*

    常量,默认为

    QUOTE_MINIMAL


  • Dialect.skipinitialspace


    如果为True,则

    delimiter

    后的空格会被忽略。默认为False。


  • Dialect.strict


    如果为 True,则在输入错误的 CSV 时抛出 Error 异常。默认值为 False。

实例:

# 自定义Dialect
class myDialect(csv.Dialect):
    delimiter = '#' # 自定义分隔符为#
    quotechar = '"' # 用双引号引用
    escapechar = None # 无转移字符
    doublequote = True # 前后都要加双引号
    skipinitialspace = True # 跳过delimiter后的空格
    lineterminator = '\r\n' # 不知道具体原理,照着csv库源代码的excel格式写的
    quoting = csv.QUOTE_NONNUMERIC # 非数字类型的数据加上引号
csv.register_dialect('my_dialect',myDialect) # 将名字加入到注册表中
with open('my customized csv.csv','w',encoding='utf-8',newline='') as f:
    headers=['姓名','语文','数学','英语']
    mywriter=csv.DictWriter(f,fieldnames=headers,dialect='my_dialect')
    data=[{'姓名':'小红','语文':100,'数学':99,'英语':80},
          {'姓名':'小明','语文':90,'数学':100,'英语':95},
          {'姓名':'小刚','语文':95,'数学':95,'英语':90}]
    mywriter.writeheader()
    mywriter.writerows(data)

写入文件内容:

在这里插入图片描述

可以看出,确实按照我自定义的格式写入了。所以大家以后在按照某种特定格式写入文件时,可以尝试一下自定义

dialect

!但是更复杂的格式,估计只能靠万能的字符串格式化了。



其他函数和变量


csv.list_dialects()-> list[str]


返回目前已经定义好的dialect的名字。

print(csv.list_dialects()) # ['excel', 'excel-tab', 'unix']


csv.register_dialect(name[, dialect[, **fmtparams]])


将dialect起名为name,添加到注册表中。


csv.unregister_dialect(name)


从注册表删除名字为name的dialect。


csv.get_dialect(name)


获取名字为name的dialect。


class csv.excel


excel 类定义了 Excel 生成的 CSV 文件的常规属性。它在注册表中的名称是

'excel'



csv库源代码内容:

在这里插入图片描述


class csv.excel_tab



excel_tab

类定义了 Excel 生成的、制表符分隔的 CSV 文件的常规属性。它在注册表中的名称是

'excel-tab'


class csv.unix_dialect



unix_dialect

类定义了在 UNIX 系统上生成的 CSV 文件的常规属性,即使用

'\n'

作为换行符,且所有字段都有引号包围。它在注册表中的名称是

'unix'

在这里插入图片描述


class csv.Sniffer


Sniffer 类用于推断 CSV 文件的格式。

Sniffer 类提供了两个方法:

sniff(sample, delimiters=None)

分析给定的 sample 并返回一个 Dialect 子类,该子类中包含了分析出的格式参数。如果给出可选的 delimiters 参数,则该参数会被解释为字符串,该字符串包含了可能的有效定界符。

has_header(sample)

分析 sample 文本(假定为 CSV 格式),如果发现其首行为一组列标题则返回 True。 在检查每一列时,将考虑是否满足两个关键标准之一来估计 sample 是否包含标题:

第二至第 n 行包含数字值

第二至第 n 行包含字符串值,其中至少有一个值的长度与该列预期标题的长度不同。

会对第一行之后的二十行进行采样;如果有超过一半的列 + 行符合标准,则返回 True。



版权声明:本文为weixin_55697913原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。