CSV(comma-separated values) 是跨多种形式导入导出数据的标准格式,比如 MySQL、Excel。

它以纯文本存储数和文本。文件的每一行就代表一条数据,每条记录包含了由逗号分隔的一个或多个属性值。这个标准格式的名字来源就是每条记录是用逗号将其属性分隔的。

即使有这个非常明显的命名标准,而实际上却没有一个官方的标准 CSV 格式,有可能是以一些比较类似的分隔符来分隔数据,虽然它们的扩展是 .csv 但是实际上却用了各种符号,空格、tab,这些也是比较流行的符号。有时由于缺少严格的定义使得数据移植变得很困难。

RFC 4180 提供了一些标准:

  • 内容为纯文本
  • 包含记录
  • 每条记录是用单个分隔字符将各属性分隔
  • 每条记录的属性序列是相同的

除非提供的 CSV 文件有额外的说明信息(比如使用 RFC 提供的标准),否则处理这种数据格式将是相当烦人的。

1.基础

Python 天生支持读取 CSV 格式数据并且是可配置的(这个我们看到是必不可少的)。在 Python 里边有个模块 csv ,它包含了 CSV 读取/生成所需的所有支持,并且它遵守 RFC 标准(除非你覆盖了相应的配置),因此默认情况下它是能够读取和生成合法的 CSV 文件。

那么,我们看看它是如何工作的:

  1. import csv
  2. with open('my.csv', 'r+', newline='') as csv_file:
  3. reader = csv.reader(csv_file)
  4. for row in reader:
  5. print(str(row))

代码中我们导入了 csv 模块并且打开了 "my.csv" 文件,将文件作为参数传给 csv.reader,调用这个方法后我们将 reader 里边的每行数据输出。

假设 'my.csv' 里边的内容为:

 

  1. my first column,my second column,my third column
  2. my first column 2,my second column 2,my third column 2

那么我们运行这个代码后,相应的输出:

 

  1. ['my first column', 'my second column', 'my third column']
  2. ['my first column 2', 'my second column 2', 'my third column 2']

生成和读取一样的简单:

  1. import csv
  2. rows = [['1', '2', '3'], ['4', '5', '6']]
  3. with open('my.csv', 'w+', newline='') as csv_file:
  4. writer = csv.writer(csv_file)
  5. for row in rows:
  6. writer.writerow(row)
  7. with open('my.csv', 'r+', newline='') as csv_file:
  8. reader = csv.reader(csv_file)
  9. for row in reader:
  10. print(str(row))

在 csv 文件的数据会是:

  1. 1,2,3
  2. 4,5,6

输出的内容:

 

  1. ['1', '2', '3']
  2. ['4', '5', '6']

到这里我们都非常清楚代码逻辑。我们将文件作为参数给 writer,以写模式打开,然后用它来写每一行数据。下边是更灵活的方式:

  1. import csv
  2. def read(file_location):
  3. with open(file_location, 'r+', newline='') as csv_file:
  4. reader = csv.reader(csv_file)
  5. return [row for row in reader]
  6. def write(file_location, rows):
  7. with open(file_location, 'w+', newline='') as csv_file:
  8. writer = csv.writer(csv_file)
  9. for row in rows:
  10. writer.writerow(row)
  11. def raw_test():
  12. columns = int(input("How many columns do you want to write? "))
  13. input_rows = []
  14. keep_going = True
  15. while keep_going:
  16. input_rows.append([input("column {}: ".format(i + 1)) for i in range(0, columns)])
  17. ui_keep_going = input("continue? (y/N): ")
  18. if ui_keep_going != "y":
  19. keep_going = False
  20. print(str(input_rows))
  21. write('raw.csv', input_rows)
  22. written_value = read('raw.csv')
  23. print(str(written_value))
  24. raw_test()

我们询问用户每行需要的列数然后是否继续输入下一行,随后我们输出读入的一般数据并且将这些内容生成到一个叫 raw.csv,然后继续这样一个过程。当我们运行这个程序,相关的内容如下:

 

  1. How many columns do you want to write? 3
  2. column 1: row 1, column 1
  3. column 2: row 1, column 2
  4. column 3: row 1, column 3
  5. continue? (y/N): y
  6. column 1: row 2, column 1
  7. column 2: row 2, column 2
  8. column 3: row 3, column 3
  9. continue? (y/N):
  10. [['row 1, column 1', 'row 1, column 2', 'row 1, column 3'], ['row 2, column 1', 'row 2, column 2', 'row 3, column 3']]
  11. [['row 1, column 1', 'row 1, column 2', 'row 1, column 3'], ['row 2, column 1', 'row 2, column 2', 'row 3, column 3']]
  12. Process finished with exit code 0

当然我们的 raw.csv 内容是:

 

  1. "row 1, column 1","row 1, column 2","row 1, column 3"
  2. "row 2, column 1","row 2, column 2","row 3, column 3"

CSV 格式的另一个规则就是引号。在上边的例子中,每一个输入都包含一个逗号,而逗号是我们的分隔符,所以这个逗号被放到了引号(标准的默认值)中间表示在此间的并非分隔符而只是每列中的符号而已。

虽让我推荐保留标准的配置信息,不过也存在一些情况需要更改默认配置,毕竟你没法控制的数据提供方给出的 csv 文件。因此,我不得不教你如何调整配置(beware, 责任越大权力越大)。

你能够通过设置 delimiter 和 quotechar 来配置分隔符和引用符:

 

  1. import csv
  2. def read(file_location):
  3. with open(file_location, 'r+', newline='') as csv_file:
  4. reader = csv.reader(csv_file, delimiter=' ', quotechar='|')
  5. return [row for row in reader]
  6. def write(file_location, rows):
  7. with open(file_location, 'w+', newline='') as csv_file:
  8. writer = csv.writer(csv_file, delimiter=' ', quotechar='|')
  9. for row in rows:
  10. writer.writerow(row)
  11. def raw_test():
  12. columns = int(input("How many columns do you want to write? "))
  13. input_rows = []
  14. keep_going = True
  15. while keep_going:
  16. input_rows.append([input("column {}: ".format(i + 1)) for i in range(0, columns)])
  17. ui_keep_going = input("continue? (y/N): ")
  18. if ui_keep_going != "y":
  19. keep_going = False
  20. print(str(input_rows))
  21. write('raw.csv', input_rows)
  22. written_value = read('raw.csv')
  23. print(str(written_value))
  24. raw_test()

现在我们的输出值为:

 

  1. How many columns do you want to write? 3
  2. column 1: row 1 column 1
  3. column 2: row 1 column 2
  4. column 3: row 1 column 3
  5. continue? (y/N): y
  6. column 1: row 2 column 1
  7. column 2: row 2 column 2
  8. column 3: row 2 column 3
  9. continue? (y/N):
  10. [['row 1 column 1', 'row 1 column 2', 'row 1 column 3'], ['row 2 column 1', 'row 2 column 2', 'row 2 column 3']]
  11. [['row 1 column 1', 'row 1 column 2', 'row 1 column 3'], ['row 2 column 1', 'row 2 column 2', 'row 2 column 3']]

我们的 raw.csv 文件中结果是:

 

  1. |row 1 column 1| |row 1 column 2| |row 1 column 3|
  2. |row 2 column 1| |row 2 column 2| |row 2 column 3|

我们可以看到,新分隔符已经变成了空格,而我们的引用符变成了管道,这主要是空格在每个文本数据中都有包含,因此 writer 强制使用管道来划分。

writer 的引用策略同样是可配置的,能够用的参数如下:

  • csv.QUOTE_ALL: 把每列都扩起来,无论是否包含分隔符
  • csv.QUOTE_MINIMAL: 只将包含分隔符的列扩起来
  • csv.QUOTE_NONNUMBERIC: 将所有非数值的列扩起来
  • csv.QUOTE_NONE: 不扩起来。这种方式强制用户检查每列的输入中是否包含分隔符,如果不检测,读取的列数将会是错误的。

读/写字点数据

我们已经看过了一些基础的读取/生成 CSV 数据的例子,不过在实际环境中,我们并不希望 CSV 文件那么的混乱,我们需要它们给出里边每一个列所表示的意义。
 
同样,实际环境下我们的数据不一定都是在数组中,我们有的是一些业务模型并且易懂。通常我们会使用字典来达到这个目的,python 相应提供了从 CVS 中读取/生成字典的工具。
 
代码差不多这个样子:

  1. import csv
  2. dictionaries = [{'age': '30', 'name': 'John', 'last_name': 'Doe'}, {'age': '30', 'name': 'Jane', 'last_name': 'Doe'}]
  3. with open('my.csv', 'w+') as csv_file:
  4. headers = [k for k in dictionaries[0]]
  5. writer = csv.DictWriter(csv_file, fieldnames=headers)
  6. writer.writeheader()
  7. for dictionary in dictionaries:
  8. writer.writerow(dictionary)
  9. with open('my.csv', 'r+') as csv_file:
  10. reader = csv.DictReader(csv_file)
  11. print(str([row for row in reader]))


我们用一个数组的测试数据初始化 dictionaries 变量,然后我们打开一个 write 模式的文件,将字典数据中的键集合写入到文件中。首先我们做的就是写键集合,然后再写数组中的字典,一个字典一行。
 
接下来我们以 read 模式打开同一个文件,获取此文件的 reader,然后将其打印成数组。输出结果如下:

  1. [{'name': 'John', 'age': '30', 'last_name': 'Doe'}, {'name': 'Jane', 'age': '30', 'last_name': 'Doe'}]


输出的 CSV 文件如下:

  1. name,last_name,age
  2. John,Doe,30
  3. Jane,Doe,30


现在它看起来就舒服多了。这个 CSV 文件包含了列信息,每行按照列顺序将数据排列好。注意到我们把属性名字给了 writer,在 python 中字典是无序的,因此在给定的情况下每行的数据顺序将会是之前所指定的。
 
这种方法同样可以应用到配置了分隔符和引用符的默认 writer 和 reader 上。
 
同样,我们把代码变的更灵活些:

 

  1. import csv
  2. def read_dict(file_location):
  3. with open(file_location, 'r+') as csv_file:
  4. reader = csv.DictReader(csv_file)
  5. print(str([row for row in reader]))
  6. return [row for row in reader]
  7. def write_dict(file_location, dictionaries):
  8. with open(file_location, 'w+') as csv_file:
  9. headers = [k for k in dictionaries[0]]
  10. writer = csv.DictWriter(csv_file, fieldnames=headers)
  11. writer.writeheader()
  12. for dictionary in dictionaries:
  13. writer.writerow(dictionary)
  14. def dict_test():
  15. input_rows = []
  16. keep_going = True
  17. while keep_going:
  18. name = input("Name: ")
  19. last_name = input("Last Name: ")
  20. age = input("Age: ")
  21. input_rows.append({"name": name, "last_name": last_name, "age": age})
  22. ui_keep_going = input("continue? (y/N): ")
  23. if ui_keep_going != "y":
  24. keep_going = False
  25. print(str(input_rows))
  26. write_dict('dict.csv', input_rows)
  27. written_value = read_dict('dict.csv')
  28. print(str(written_value))
  29. dict_test()

我们现在运行这个代码,会有如下的结果:

Name: John
Last Name: Doe
Age: 30
continue? (y/N): y
Name: Jane
Last Name: Doe
Age: 40
continue? (y/N):
[{'age': '30', 'last_name': 'Doe', 'name': 'John'}, {'age': '40', 'last_name': 'Doe', 'name': 'Jane'}]
[{'age': '30', 'last_name': 'Doe', 'name': 'John'}, {'age': '40', 'last_name': 'Doe', 'name': 'Jane'}]


我们的 dict.csv 内容:

age,last_name,name
30,Doe,John
40,Doe,Jane


一些注意点。就像我之前说过的,在 python 中字典是无序的,所以当你从一个字典中提取键集合并将数据写入到一个 CSV 文件的时候你应该将它们排好序始终使它们保持同样的顺序。你并不知道你的用户会用什么方法来读取这些数据,当然,在实际环境中 CSV 文件总是在增长的,你总是在增加文件的行,而不是覆盖它们。为了避免不必要的麻烦首先就是确保你的 CSV 文件始终看起来相同。

Python CSV Reader/Writer 例子--转载的更多相关文章

  1. python csv.reader参数指定

  2. python 使用csv.reader和csv.writer读写文件并转换成dataframe格式

    import csv import pandas as pd ###csv.reader用法 ''' f=open(r"C:\Users\admin\pycdtest\wanyue\yuee ...

  3. python csv模块的reader是一个迭代器,无法多次迭代

    在一个项目中,我需要多次遍历一个文本,该文本我是用csv.reader读取的.但后来发现,本文只对第一次循环有用,而之后的循环均为空白.经过排错后,我确定问题就出现在csv.reader()这一步.之 ...

  4. Python CSV文件处理/读写及With as 用法

    可以不使用CSV模块 逐行处理: for line in open("samples/sample.csv"): title, year, director = line.spli ...

  5. Python csv.md

    csv csv模块可以用于处理从电子表格和数据库导出的数据到带有字段和记录格式的文本文件,通常称为逗号分隔值(csv)格式,因为逗号通常用于分隔记录中的字段. Reading csv.reader(c ...

  6. Python CSV模块简介

    Table of Contents 1. CSV 1.1. 简介 1.2. 字典方式地读写 1.3. 其它 2. 参考资料 CSV csv文件格式是一种通用的电子表格和数据库导入导出格式.最近我调用R ...

  7. Python CSV模块处理文件读写

    下面是一个简单的csv文件 Title,Release Date,Director And Now For Something Completely Different,1971,Ian MacNau ...

  8. Python CSV 超简明用法

    平常经常会用CSV存储数据,不可避免的会跟CSV文件的读写操作扯上关系. Python有CSV这个Package来解决这个问题,官网也有比较详细的教程 https://docs.python.org/ ...

  9. Python csv模块的使用

    1.csv简介 CSV (Comma Separated Values),即逗号分隔值(也称字符分隔值,因为分隔符可以不是逗号),是一种常用的文本 格式,用以存储表格数据,包括数字或者字符.很多程序在 ...

随机推荐

  1. Spark2.x学习笔记:Spark SQL程序设计

    1.RDD的局限性 RDD仅表示数据集,RDD没有元数据,也就是说没有字段语义定义. RDD需要用户自己优化程序,对程序员要求较高. 从不同数据源读取数据相对困难. 合并多个数据源中的数据也较困难. ...

  2. [py]letcode第一题求和

    letcode第一题, tm的不好弄. 想了很久想到了一个粗蠢的解决办法. Given an array of integers, return indices of the two numbers ...

  3. Java-二叉树算法

    二叉树算法的排序规则: 1.选择第一个元素作为根节点 2.之后如果元素大于根节点放在右子树,如果元素小于根节点,则放在左子树 3.最后按照中序遍历的方式进行输出,则可以得到排序的结果(左->根- ...

  4. logistics回归

    logistic回归的基本思想 logistic回归是一种分类方法,用于两分类问题.其基本思想为: a. 寻找合适的假设函数,即分类函数,用以预测输入数据的判断结果: b. 构造代价函数,即损失函数, ...

  5. char* a与char a[]的区别

    char *a 与char a[] 的区别   char *a = "hello" 中的a是指向第一个字符‘a'的一个指针 char a[20] = "hello&quo ...

  6. 多项式函数插值:全域多项式插值(一)单项式基插值、拉格朗日插值、牛顿插值 [MATLAB]

    全域多项式插值指的是在整个插值区域内形成一个多项式函数作为插值函数.关于多项式插值的基本知识,见“计算基本理论”. 在单项式基插值和牛顿插值形成的表达式中,求该表达式在某一点处的值使用的Horner嵌 ...

  7. Trove系列(八)——Trove的配置管理相关的功能介绍

    概述MySQL 配置管理功能允许Trove 用户重载由Trove服务的操作者提供的缺省MySQL配置环境.这是通过影响MySQL 的includedir 命令来实现的.这些MySQL 的include ...

  8. Learning to Rank算法介绍:RankNet,LambdaRank,LambdaMart

    之前的博客:http://www.cnblogs.com/bentuwuying/p/6681943.html中简单介绍了Learning to Rank的基本原理,也讲到了Learning to R ...

  9. 在IBM学到的东西,到底对我的程序生涯产生了多大的影响

    我和很多人交流过一个有趣的现象,那就是刚毕业到30岁这段时间,会觉得时间过得很慢,总觉得自己还很年轻,但是一旦过了30岁,时间就如白驹过隙,一年又一年飞逝而过. 我自己也是,眼瞅着毕业快15年了,15 ...

  10. Python Web学习笔记之Cookie,Session,Token区别

    一.Cookie,Session,Token简介 # 这三者都解决了HTTP协议无状态的问题 session ID or session token is a piece of data that i ...