Python 标准库中的 csv 包

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 csvwith 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, CityJohn, 25, New YorkAlice, 30, Los AngelesBob, 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 = Nonedoublequote = Trueskipinitialspace = Falselineterminator = '\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 = Trueskipinitialspace = Falselineterminator = '\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]])"""passdef 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 andthe 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.mzph.cn/news/597054.shtml

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

相关文章

解决docker容器内无法连接宿主redis

背景 小程序的发短信服务挂了&#xff0c;随查看日志&#xff0c;该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口&#xff0c;那大概是redis出错了。 首先查看了redis是否正常启动&#xff0c;检查出服务正常。 由于小…

Flappy Bird QDN PyTorch博客 - 代码解读

Flappy Bird QDN PyTorch博客 - 代码解读 介绍环境配置项目目录结构QDN算法重要函数解读preprocess(observation)DeepNetWork(nn.Module)BirdDQN类主程序部分 介绍 在本博客中&#xff0c;我们将介绍如何使用QDN&#xff08;Quantile Dueling Network&#xff09;算法&#xf…

【Mybatis】我抄袭了Mybatis,手写一套MyMybatis框架:编写一个引入MyMybatis框架的正常项目

上一篇文章中&#xff0c;我们学习了使用mybatis框架连接mysql。在这篇文章中&#xff0c;我们将聚焦于我们的调用方&#xff0c;即相应的实际项目&#xff0c;其中包含了对mymybatis框架的引用。以一个常见而又典型的例子来说明这一点——制作一款学生管理系统&#xff08;伪&…

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

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

Maven简介及环境搭建和基本使用(Java开发中的实用工具)

一、概述 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它 用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、 测试、打包和发布等工作。 Maven的相关概念 pom.xml文件&#xff1a;里面可以配置相关信息&#xff0c;指导ma…

【SpringBoot开发】之商城项目案例(沙箱支付)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。&#x1f3af…

MySQL数据库索引优化实战

目录 一、前言 二、准备工作 2.1 用户表&#xff08;TB_USER) 2.2 商品表&#xff08;TB_SKU) 2.3 订单表&#xff08;TB_ORDER&#xff09; 三、实例分析 3.1 索引提升查询性能 3.2 多表查询 3.3 索引失效 四、总结 一、前言 在数据库的应用中&#xff0c;性能优化…

类加载机制之双亲委派模型、作用、源码、SPI打破双亲委派模型

双亲委派模型 双亲委派工作机制双亲委派的作用双亲委派的实现源码SPI打破双亲委派 应用程序是由三种类加载器相互配合&#xff0c;从而实现类加载&#xff0c;除此之外还可以加入自己定义的类的加载器。 类加载器之间的层次关系&#xff0c;称为双亲委派模型&#xff08;Parent…

2024最全面且有知识深度的web3开发工具、web3学习项目资源平台

在Web3技术迅速发展的时代&#xff0c;寻找一个综合且深入的Web3开发工具和学习项目资源平台变得至关重要。今天&#xff0c;我将向大家介绍一个非常有价值的网站&#xff0c;它就是https://web3x.world 。 Web3X是一个全面而深入的Web3开发者社区&#xff0c;为开发者们提供了…

【深度学习】各领域常用的损失函数汇总(2024最新版)

目录 1、L1 损失、平均绝对误差&#xff08;L1 Loss、Mean Absolute Error&#xff0c;MAE&#xff09; 2、L2 损失、均方误差&#xff08;L2 Loss、Mean Squared Error&#xff0c;MSE&#xff09; 3、交叉熵损失&#xff08;Cross-Entropy Loss&#xff09; 4、混合损失&…

webpack的深入学习与实战(持续更新)

一、何为Webpack Webpack是 一个开源的JavaScript模块打包工具&#xff0c;其最核心的功能是解决模块之间的依赖&#xff0c;把各个模块按照特定的规则和顺序组织在一起&#xff0c;最终合并为一个JS文件或多个。 二、带宽的换算 目前我们的云服务器带宽为5M 三 、bundle 体…

【算法挨揍日记】day34——647. 回文子串、5. 最长回文子串

647. 回文子串 647. 回文子串 题目描述&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&am…

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生 我能否相信自己温暖和百感交集的旅程前言和后记 《温暖和百感交集的旅程》作者余华&#xff0c;之前读完的一本书&#xff0c;已经不太记得内容了&#xff0c;看着笔记整理的这篇书…

【进程间通信】

什么是进程通信 进程通信&#xff08; InterProcess Communication&#xff0c;IPC&#xff09;就是指进程之间的信息的传播和交换。 进程是分配系统资源的单位&#xff0c;包括内存地址空间&#xff0c;为了保证安全&#xff0c;一个进程不能直接访问另一个进程的地址空间&a…

CMake入门教程【核心篇】属性管理set_property和get_property

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.概述2.设置属性 - …

FPGA设计时序约束十五、Set_Bus_Skew

目录 一、序言 二、Set Bus Skew 2.1 基本概念 2.2 设置界面 2.3 命令语法 2.4 报告分析 三、工程示例 3.1 工程代码 3.2 时序报告 四、参考资料 一、序言 在时序约束中&#xff0c;对时钟的约束除了set clock latency,set clock uncertainty,set input jitter外&…

51、全连接 - 特征的全局融合

Resnet50 中的核心算法,除了卷积、池化、bn、relu之外,在最后一层还有一个全连接。 下图是 Resnet50 网络结构结尾的部分,最后一层 Gemm(通用矩阵乘法)实现的就是全连接操作。而矩阵乘法我们之前介绍过,传送门在:矩阵乘。 卷积也好,矩阵乘法也好,其目的都是为了完成神…

JavaWeb基础(1)- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件监听、正则表达式)

JavaWeb基础&#xff08;1&#xff09;- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件监听、正则表达式) 文章目录 JavaWeb基础&#xff08;1&#xff09;- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件…

2024.1.2 Redis 数据类型 Stream、Geospatial、HyperLogLog、Bitmaps、Bitfields 简介

目录 引言 Stream 类型 Geospatial 类型 HyperLogLog 类型 Bitmaps 类型 Bitfields 类型 引言 Redis 最关键&#xff08;应用广泛、频繁使用&#xff09;的五个数据类型 StringListHashSetZSet 下文介绍的数据类型一般适合在特定的场景中使用&#xff01; Stream 类型 St…

Redis命令---Hash(哈希)篇 (超全)

目录 1.Redis Hmset 命令 - 同时将多个 field-value (域-值)对设置到哈希表 key 中。简介语法可用版本: > 2.0.0返回值: 如果命令执行成功&#xff0c;返回 OK 。 示例 2.Redis Hmget 命令 - 获取所有给定字段的值简介语法可用版本: > 2.0.0返回值: 一个包含多个给定字段…