Python 标准库中的 csv 包

news2024/11/28 16:40:45

0. Abstract

官方文档很罗嗦,长篇大论例子少。本文将举例说明 csv 包的用法,然后补充一些必要的说明。

1.0 CSV 文件

CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符,并且每一行表示一个记录。

以下是一个简单的示例,展示了一个包含姓名、年龄和城市信息的 CSV 文件:

Name, Age, City
John, 25, New York
Alice, 30, Los Angeles
Bob, 35, Chicago

在上述示例中,第一行是标题行,包含了三个字段(field)的名称:Name、Age 和 City。接下来的每一行都是一个记录,每个字段之间由逗号进行分隔

在 Python 中,可以使用内置的 csv 模块来读取和写入 CSV 文件。该模块提供了方便的函数和方法来处理 CSV 数据,例如 csv.reader() 用于读取 CSV 文件,csv.writer() 用于写入 CSV 文件,以及其他用于设置分隔符引号字符等的选项。

1.1 读文件 reader(iterable, dialect='excel', *args, **kwargs)

这个函数标签是 PyCharm 生成的伪标签,实际的代码在底层,不是 python 语言,故无法查看。读:

import csv

with open('demo.py', 'r') as csvfile:  # 记刚才生成的 csv 文件名为 'demo.py'
	samples = csv.reader(csvfile)
	for sample in samples:
		print(sample)

### output ###
['Name', ' Age', ' City']
['John', ' 25', ' New York']
['Alice', ' 30', ' Los Angeles']
['Bob', ' 35', ' Chicago']
参数 iterable

按照 reader(iterable, dialect='excel', *args, **kwargs),它是可以接收任何 iterable 对象的,我试了一下,确实可以:

for row in csv.reader('abc', delimiter=','):
	print(row)

### output ###
['a']
['b']
['c']
# 如果 ('abc', 'def'), 则 ['abc'] ['def']

但是这个迭代器要返回 str 才行,如果 csv.reader((1, 2)),则出现错误:

_csv.Error: iterator should return strings, not int (did you open the file in text mode?)

由此看来,csv.reader 是需要 iterable 返回 str,然后再对 str 根据 delimiter 进行分割:

for row in csv.reader(('a,bc', 'def'), delimiter='b'):
	print(row)
### output ###
['a,', 'c']
['def']

果然把 ‘a,bc’ 中的 ‘b’ 当分隔符了。还发现,每行的分割数量可以不一致

小结reader(iterable, dialect='excel', *args, **kwargs) 接收一个字符串迭代器,返回一个字符串列表迭代器:迭代过程中,根据 delimiter 把字符串分割成字符串列表。如 csv.reader('abc', delimiter=','),迭代 a, b, c 三个字符串,每个字符串根据 ',' 分割,形成列表 ['a'], ['b'], ['c']

重温 open()

那么 open('demo.py', 'r') 是一个 str 迭代器咯?是的:

open 返回的对象是 TextIOWrapper,它在 io 包中,类结构如上图所示,它是个迭代器。

之前只知道常见的文件读取函数:

f.read()  # 读取全部文本,返回一个字符串。这种方法适用于一次性处理小的文件。
f.readline()  # 按行读取文件,每次返回一个字符串。
f.readlines()  # 读取全部文本,返回一个字符串列表。

不知道 f 本身是什么,既然现在知道它是迭代器,那看一看 for ... in ... 会发生什么:

with open('demo.csv', 'r') as f:
	for item in f:
		print(item)

### output ###
Name, Age, City

John, 25, New York

Alice, 30, Los Angeles

Bob, 35, Chicago

每个迭代元素是文件中文本的一行,并带有 \n 换行符,这和 f.readlines() 是一样的,只不过后者是一次性读取所有行,前者是边读边迭代。不止如此,既然能 with,那么它肯定也是上下文管理器。这个迭代器是可关闭的。

回到 csv.reader(csvfile),看一看文件迭代器关闭后继续迭代 csv.reader(csvfile) 会怎样:

with open('demo.py', 'r') as csvfile:
	samples = csv.reader(csvfile)
for sample in samples:  # csv 文件已关闭
	print(sample)

# ValueError: I/O operation on closed file.

报了 ValueError: I/O operation on closed file. 错,这和读写已关闭的文件是一样的。也就是说,csv.reader(csvfile) 并不是一次性读取文件返回给 samples 对象,它只是包装了 csvfile实际的读写操作还是csvfile 对象完成的。但很遗憾,只能到这,samples = csv.reader(csvfile) 返回的 _reader 类型到底是怎样的,无法得知。

小结reader(csvfile) 包装一个文件对象 csvfile (是个字符串迭代器),每次迭代一行,根据 delimiter 把这行字符串分割成字符串列表,过程中 csvfile 不能关闭。

再读文档就明白了:

The “iterable” argument can be any object that returns a line of input for each iteration, such as a file object or a list. The optional “dialect” parameter is discussed below. The function also accepts optional keyword arguments which override settings provided by the dialect.
The returned object is an iterator. Each iteration returns a row of the CSV file (which can span multiple input lines).

1.2 参数配置

reader(iterable, dialect='excel', *args, **kwargs)csv.reader('abc', delimiter=',') 来看,参数可以通过类似 delimiter=',' 的键值对进行配置,但不知道都有哪些参数可配置。注意到 dialect='excel',在文档中有这么一段话:

The function also accepts optional keyword arguments which override settings provided by the dialect.

也即 dialect='excel' 提供了参数设置。继续看文档怎么写(翻译):

1.2.1 Dialect Registration:

ReadersWriters 都支持 dialect 参数,该参数是对一组 setting 的方便 handle。当 dialect 参数是字符串时,它标识模块中预先注册的一种 dialect。如果它是一个类或实例,则参数的属性用作读取器或写入器的设置:

class excel(Dialect):
	delimiter = ','
	quotechar = '"'
	escapechar = None
	doublequote = True
	skipinitialspace = False
	lineterminator = '\r\n'
	quoting = QUOTE_MINIMAL

SETTINGS 意义:

  • quotechar - 指定一个字符作为 quoting character (引号符);
  • delimiter - 指定一个字符作为字段 separator (分隔符) ;
  • skipinitialspace - 如何解释 whitespace which immediately follows a delimiter,如果为 False,则把分隔符后的空格当作字段值的一部分;
  • lineterminator - 结束一行的字符序列,应该是 '\n' 之类的;
  • quoting - 控制 writer 函数给字段值加引号的规则,可以是以下 module constants
         ~~~~     csv.QUOTE_MINIMAL = 0 – 必要时才加引号,例如,当字段值包含引号或分隔符时;
         ~~~~     csv.QUOTE_ALL = 1“always” 加引号;
         ~~~~     csv.QUOTE_NONNUMERIC = 2 – 非数字的字段值加引号;
         ~~~~     csv.QUOTE_NONE = 3never 加引号;
  • escapechar - 指定在引号设置为 QUOTE_NONE 时用于转义分隔符的字符;
  • doublequote - 处理字段内部的引号,如果为 True,读文件时两个连续的引号解释为一个,写入时每个引号写成两个。

还有两个定义好的 Dialect 类:

class excel_tab(excel):
	"""Describe the usual properties of Excel-generated TAB-delimited files."""
	delimiter = '\t'
register_dialect("excel-tab", excel_tab)

class unix_dialect(Dialect):
	"""Describe the usual properties of Unix-generated CSV files."""
	delimiter = ','
	quotechar = '"'
	doublequote = True
	skipinitialspace = False
	lineterminator = '\n'
	quoting = QUOTE_ALL
register_dialect("unix", unix_dialect)

如果想自己定义 Dialect,只需要模仿着继承 class Dialect 就行。然后就是注册。

注册 register_dialect("unix", unix_dialect)

def register_dialect(name, dialect=None, **fmtparams=None): # real signature unknown; restored from __doc__
	"""
	Create a mapping from a string name to a dialect class.
		dialect = csv.register_dialect(name[, dialect[, **fmtparams]])
	"""
	pass

注册 Dialect,就是给定义的 Dialect 关联一个字符串名字,以便以类似 dialect='excel' 的方式设置参数,当然直接给类或实例也是可以的。

Dialect 类中的参数可以直接以 **kwargs 键值对的方式送到 csv.reader() 函数中。

Dialect 相关的几个函数

这些都是 PyCharm 根据文档生成的函数伪标签:

def get_dialect(name): # real signature unknown; restored from __doc__
	"""
	Return the dialect instance associated with name.
		dialect = csv.get_dialect(name)
	打印出来得到类似 <_csv.Dialect object at 0x000002606C5EC990> 的东西
	"""
	pass
def list_dialects(): # real signature unknown; restored from __doc__
	"""
	Return a list of all know dialect names.
		names = csv.list_dialects()
	已注册的 Dialect 列表吧
	"""
	pass
def register_dialect(name, dialect=None, **fmtparams=None): # real signature unknown; restored from __doc__
	"""
	Create a mapping from a string name to a dialect class.
		dialect = csv.register_dialect(name[, dialect[, **fmtparams]])
	"""
	pass

def unregister_dialect(name): # real signature unknown; restored from __doc__
	"""
	Delete the name/dialect mapping associated with a string name.
		csv.unregister_dialect(name)
	"""
	pass

试验:

class B(csv.excel):
	delimiter = 'b'  # 设置字符 b 为分隔符

csv.register_dialect('b', B)  # 注册名为 b
print(csv.list_dialects())

### output ###
['excel', 'excel-tab', 'unix', 'b']  # 多了一个 `b`

2. 几个函数

def field_size_limit(limit=None):  # real signature unknown; restored from __doc__
	"""
	Sets an upper limit on parsed fields. csv.field_size_limit([limit])

	Returns old limit. If limit is not given, no new limit is set and
	the old limit is returned
	"""
	pass

设置了字段的最大长度,如果超过 limit,则报错:

_csv.Error: field larger than field limit (limit值)

1.3 写 csv 文件

def writer(fileobj, dialect='excel', *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__ 
	"""
	csv_writer = csv.writer(fileobj [, dialect='excel'] [optional keyword args])
		for row in sequence:
			csv_writer.writerow(row)
		[or]
		csv_writer = csv.writer(fileobj [, dialect='excel'] [optional keyword args])
		csv_writer.writerows(rows)

	The "fileobj" argument can be any object that supports the file API.
	"""
	pass

试一试:

sequence = [
	['A', 18, 'Zhoukou'],
	['B', 19, 'Nanjing']
]
with open('./demo.csv', 'w') as csvfile:
	csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
	for row in sequence:
		csv_writer.writerow(row)
	csv_writer.writerows(sequence)

发现文件内容变成了:

"A",18,"Zhoukou"

"B",19,"Nanjing"

"A",18,"Zhoukou"

"B",19,"Nanjing"

即是覆盖写入的,如果把 open('./demo.csv', 'w') 中的 'w' 改成 'a',就可以追加写入了。再一次证实了 csv.reader(...)csv.writer(...) 只是包装了文件读写对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UG装配-引用集

引用集是控制组件的图素在装配体中显示与隐藏 装配体体环境控制组件显示与隐藏的四种方式 1、图层 2、引用集 3、隐藏命令 Ctrl B 4、抑制&#xff0c;取消此组件装配&#xff0c;但保留操作在导航器方便启用 引用集有两种类型 1、UG自动创建的引用集 2、用户定义的引…

ElasticSearch使用Grafana监控服务状态-Docker版

文章目录 版本信息构建docker-compose.yml参数说明 创建Prometheus配置文件启动验证配置Grafana导入监控模板模板说明 参考资料 版本信息 ElasticSearch&#xff1a;7.14.2 elasticsearch_exporter&#xff1a;1.7.0&#xff08;latest&#xff09; 下载地址&#xff1a;http…

部署清华ChatGLM-6B(Linux版)

引言 前段时间,清华公布了中英双语对话模型 ChatGLM-6B,具有60亿的参数,初具问答和对话功能。最!最!最重要的是它能够支持私有化部署,大部分实验室的服务器基本上都能跑起来。因为条件特殊,实验室网络不通,那么如何进行离线部署呢? 「部署环境」:CUDA Version 11.0,…

中国移动联合玻色量子打造“人人可用的量子计算”——恒山光量子算力平台公测上线

​2023年12月1日&#xff0c;中国移动云能力中心&#xff08;简称“移动云”&#xff09;联合北京玻色量子科技有限公司&#xff08;简称“玻色量子”&#xff09;共同打造的“五岳量子计算云平台——恒山光量子算力平台”在苏州正式发布。这是玻色量子继2023年5月16日成功发布…

医院信息系统集成平台—统一身份认证授权平台

统一的数字身份管理包括统一身份管理与授权管理。身份管理和授权管理是访问控制的前提,身份管理对用户的身份进行标识与鉴别;授权管理对用户访问资源的权限进行标识与管理。统一身份管理与授权管理系统作为安全管理中心的一部分,部署于安全管理区域。 医院集成信息平台在医…

大数据应用安全策略包括什么

大数据应用安全策略是为了保障大数据应用中的数据安全而采取的一系列措施&#xff0c;其重要性不容小觑。以下是大数据应用安全策略所包含的主要内容&#xff1a; 一、数据加密与安全存储 数据加密&#xff1a;对于敏感数据&#xff0c;应采用加密技术进行保护&#xff0c;包括…

关于酒的几点思考

你说什么情况下&#xff0c;会让两个大男人手牵着手走路&#xff1f;甚至十指相扣。 不言而明&#xff0c;那肯定是“喝大了”之后。当酒精麻痹了人的神经之后&#xff0c;会让人忘却一切烦恼&#xff0c;让人回归“本真”。当血液中乙醇浓度在0.05-0.1%时&#xff0c;人开始朦…

Android 文字垂直排列,文字向右旋转90度

public class VerticalTextView extends View {private final int ROTATION_ANGLE 90; // 旋转角度&#xff0c;用于将文本垂直排列private String text; // 要显示的文本private TextPaint textPaint; // 用于绘制文本的画笔private Rect textBounds;// 文本边界float x, y;/…

解析为什么Go语言要使用[]rune而不是string来表示中文字符

众所周知&#xff0c;Go语言中有以下这些数据类型。但rune32这个go语言特有的数据类型&#xff0c;比较有意思却经常遭到忽视。所以今天探索学习一下这个数据类型的功能、用法。 Go基本数据类型 布尔&#xff1a;bool 字符串&#xff1a;string 整数&#xff1a; int int8 …

实现vue加载指令 v-loading

文章目录 为什么使用指令实现 loading具体实现封装准备实现 loading 效果loading 显示与隐藏使用修饰符扩展 完整代码与结语 本文不会详细的说明 vue 中指令这些知识点&#xff0c;如果存在疑问&#xff0c;请自行查阅文档或者其他资料 为什么使用指令实现 loading 在日常的开…

(Linux)虚拟机配置固定IP

Linux操作系统的IP地址是通过DHCP服务获取的&#xff0c;也就是动态获取IP地址&#xff0c;每次重启设备后都会获取一次&#xff0c;会导致IP地址频繁变更&#xff0c;为了不频繁更新映射关系&#xff0c;我们需要IP地址固定下来。 1.在VM中配置IP地址网关和网段 打开虚拟网络…

Prometheus-AlertManager 邮件告警

环境,软件准备 本次演示环境&#xff0c;我是在虚拟机上安装 Linux 系统来执行操作&#xff0c;以下是安装的软件及版本&#xff1a; System: CentOS Linux release 7.6Docker: 24.0.5Prometheus: v2.37.6Consul: 1.6.1 docker 安装prometheus,alertmanage,说明一下这里直接将…

2024-01-04 用llama.cpp部署本地llama2-7b大模型

点击 <C 语言编程核心突破> 快速C语言入门 用llama.cpp部署本地llama2-7b大模型 前言一、下载llama.cpp以及llama2-7B模型文件二、具体调用总结 使用协议: License to use Creative Commons Zero - CC0 该图片个人及商用免费&#xff0c;无需显示归属&#xff0c;但如果…

Proxy 与 defineProperty 的理解、区别、优势、劣势

一、Object.defineProperty() 文档&#xff1a;Object.defineProperty() - JavaScript | MDN 作用&#xff1a;对一个对象进行操作的方法。可以为一个对象增加一个属性&#xff0c;同时也可以对一个属性进行修改和删除。 它是在 ES5 中引入的&#xff0c;使用了 getter 和 s…

windows机器上安装mysql

0、mysql下载地址 1、参考文章 2、把Data数据目录迁移到其他盘 2.0 首先停止mysql&#xff08;任务管理器-详细信息-随便找个进程右击进入转入服务&#xff0c;找到MySQL服务&#xff0c;点击停止&#xff09; 2.1 windows的 mysql默认的data目录在C:\ProgramData\MySQL\MySQ…

【编译原理】期末预习PPT前四章笔记II

看了看学校的ppt&#xff0c;记的比较随意O.o 因为我的考试范围里边没有简答所以概念什么的没怎么记 没有简答只有选择真是太好了嘿嘿嘿 目录 I. 概述&#xff08;好多字。。&#xff09; 一、高级语言的分类 1、体裁 2、执行方式 二、各种语言的执行方式 三、编译程序…

52、全连接 - 特征与样本空间的对应关系

上一节说到经过全连接层之后,神经网络学习到的特征,会从隐层特征空间逐步映射到样本空间,这主要是由于全连接层可以融合全局的特征。 在经过全连接层之后,在 ResNet50 这个神经网络中会输出1000个特征的得分值,这1000个特征的得分值,便可以对应到图像的分类。 怎么对应…

一文讲透Linux应用编程—进程原理

文章目录 程序的开始和结束main函数由谁调用&#xff1f;程序是如何结束的&#xff1f;atexit注册进程终止处理函数return、 exit、_exit三者区别 进程环境环境变量进程运行的虚拟空间 进程的正式引入什么是进程&#xff1f;进程ID多进程调度原理 fork创建子进程为什么要创建子…

cnstd使用效果测试

使用参考&#xff1a;https://github.com/breezedeus/CnSTD/tree/master 原理参考&#xff1a;https://cnocr.readthedocs.io/zh/latest/intro-cnstd-cnocr.pdf 模型&#xff1a; 结论&#xff1a; 经过测试&#xff0c; 长文本检测效果不错&#xff0c;短文本可能角度不对 …

MO 2023 年度回顾

PART-ONE 行业态势 随着供需关系的变化&#xff0c;数据库的竞争在经历了 3 年 “百花齐放” 般的发展后&#xff0c;终于在 2023 年进入到了一个相对收拢的阶段。 2023 年&#xff0c;各个数据库厂商间很有默契地在两个方面达成了一致&#xff1a; HTAP 已经成为新一代数据…