百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python学习者的文件读写指南(基础到进阶)

off999 2024-10-02 18:47 34 浏览 0 评论

对于初学者来说,一份详尽又清晰明白的指南很重要。今天跟大家一起,好好学习Python文件读写的内容,这部分内容特别常用,掌握后对工作和实战都大有益处。

学习是循序渐进的过程,欲速则不达。文章较长,建议大家收藏,以备复习查阅哦。

1、如何将列表数据写入文件?

2、如何从文件中读取内容?

3、多样需求的读写任务

4、从with语句到上下文管理器


如何将列表数据写入文件?

首先,我们来看看下面这段代码,并思考:这段代码有没有问题,如果有问题的话,要怎么改?

li = ['python',' is',' a',' cat']

with open('test.txt','w') as f:

f.write(li)

现在公布答案,这段代码会报错:

TypeError Traceback (most recent call last)

in ()

1 with open('test.txt','w') as f:

----> 2 f.write(li)

TypeError: write() argument must be str, not list

以上代码的想法是将list列表内容写入txt文件中,但是报错 TypeError: write() argument must be str。就是说,write()方法必须接受字符串(str)类型的参数。

Python中内置了str()方法,可以返回字符串版本的对象(Return a string version of object)。所以,上面的例子中,我们试试把 f.write(li) 改为 f.write(str(li)) ,先做一下字符串类型的转化看看。代码略。

这次没有报错了,但是打开文件就傻眼了吧,写入的内容是“['python',' is',' a',' cat']”。怎么才能写成“python is a cat”呢?

文件写操作还有一个writelines()方法,它接收的参数是由字符串组成的序列(sequence),实际写入的效果是将全部字符串拼接在一起。字符串本身也是一种序列,所以当参数是字符串的时候,writelines()方法等价于write()。

# 以下3种写法等价,都是写入字符串“python is a cat”

In [20]: with open('test.txt','w') as f:

...: f.writelines(['python',' is',' a',' cat'])

...: f.writelines('python is a cat')

...: f.write('python is a cat')

# 以下2种写法等价,都是写入列表的字符串版本“['python',' is',' a',' cat']”

In [21]: with open('test.txt','w') as f:

...: f.write(str(['python',' is',' a',' cat']))

...: f.writelines(str(['python',' is',' a',' cat']))

# 作为反例,以下写法都是错误的:

In [22]: with open('test.txt','w') as f:

...: f.writelines([2018,'is','a','cat']) # 含非字符串

...: f.write(['python','is','a','cat']) # 非字符串

由上可知,当多段分散的字符串存在于列表中的时候,要用writelines()方法,如果字符串是一整段,那直接使用write()方法。如果要以整个列表的形式写入文件,就使用str()方法做下转化。

这个问题还没结束,如果列表中就是有元素不是字符串,而且要把全部元素取出来,怎么办呢?

那就不能直接使用write()和writelines()了,需要先用for循环,把每个元素取出来,逐一str()处理。

In [37]: content=[1,' is',' everything']

In [38]: with open('test.txt','w') as f:

...: for i in content:

...: f.write(str(i))

需要注意的是,writelines()不会自动换行。如果要实现列表元素间的换行,一个办法是在每个元素后面加上换行符“\n”,如果不想改变元素,最好是用for循环,在写入的时候加在末尾:for i in content: f.writelines(str(i)+“\n”).

引申一下,经过实验,数字及元祖类型也可以作为write()的参数,不需转化。但是dict字典类型不可以,需要先用str()处理一下。字典类型比较特殊,最好是用json.dump()方法写到文件,具体操作方法以及注意事项,请看喵喵之前发的《假期玩得开心也不忘充电,学习Python操作JSON,网络数据交换不用愁》.

总结一下,write()接收字符串参数,适用于一次性将全部内容写入文件;writelines()接收参数是由字符串组成的序列,适用于将列表内容逐行写入文件。str()返回Python对象的字符串版本,使用需注意。


如何从文件中读取内容?

从文件中读取内容有如下方法:

file.read([size])

从文件读取指定的字节数,如果未给定或为负则读取所有。

file.readline([size])

读取整行,包括 "\n" 字符。

file.readlines([sizeint])

读取所有行并返回列表,若给定sizeint>0,则是设置一次读多少字节,这是为了减轻读取压力。

简而言之,在不传参数的情况下,read()对应write(),读取全部内容;readlines()对应writelines(),读取全部内容(含换行符)并以列表形式返回,每个换行的内容作为列表的一个元素。

In [47]: with open('test.txt','r') as f:

...: print(f.read())

1 is everything.

python is a cat.

this is the end.

In [48]: with open('test.txt','r') as f:

...: print(f.readlines())

['1 is everything.\n', 'python is a cat.\n', 'this is the end.']

但是,以上两个方法有个缺点,当文件过大的时候,一次性读取太多内容,会对内存造成极大压力。读操作还有一个readline()方法,可以逐行读取。

In [49]: with open('test.txt','r') as f:

...: print(f.readline())

1 is everything.

readline()

读取第一行就返回,再次调用f.readline(),会读取下一行。

喵喵,是否感觉跟《超强汇总:学习Python列表,只需这篇文章就够了》学习过的生成器很像,需要不停调用next()获取下一行。

这么看来,readline()太笨拙了。那么,有什么办法可以优雅地读取文件内容呢?

回过头来看readlines()方法,它返回的是一个列表。这不奇怪么,好端端的内容为啥要返回成列表呢?

再想想writelines()方法,把字符串列表写入文件正是这家伙干的事,readlines()方法恰恰是它的逆操作!而writelines()方法要配合for循环,所以我们把readlines()与for循环结合,看看会怎样。

In [61]: with open('test.txt','r') as f:

...: for line in f.readlines():

...: print(line)

1 is everything.

python is a cat.

this is the end.

# 读取内容包含换行符,所以要strip()去掉换行符

In [62]: with open('test.txt','r') as f:

...: for line in f.readlines():

...: print(line.strip())

1 is everything.

python is a cat.

this is the end.

总结一下,readline()比较鸡肋,不咋用;read()适合读取内容较少的情况,或者是需要一次性处理全部内容的情况;而readlines()用的较多,比较灵活,因为for循环是一种迭代器,每次加载部分内容,既减少内存压力,又方便逐行对数据处理。


多样需求的读写任务

前两部分讲了文件读写的几大核心方法,它们能够起作用的前提就是,需要先打开一个文件对象,因为只有在文件操作符的基础上才可以进行读或者写的操作。

打开文件用的是open()方法,所以我们再继续讲讲这个方法。open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

open()方法的参数里file(文件)是必需的,其它参数最常用的是mode(模式)和encoding(编码)。

先说说encoding,一般来说,打开文件的编码方式以操作系统的默认编码为准,中文可能会出现乱码,需要加encoding='utf-8'。

In [63]: with open('test.txt','r') as f:

...: for line in f.readlines():

...: print(line.strip())

-----------------------

UnicodeDecodeError Traceback (most recent call last)

in ()

1 with open('test.txt','r') as f:

----> 2 for line in f.readlines():

3 print(line.strip())

UnicodeDecodeError: 'gbk' codec can't decode byte 0xa4 in position 26: illegal multibyte sequence

In [65]: with open('test.txt','r',encoding='utf-8') as f:

...: for line in f.readlines():

...: print(line.strip())

爱猫猫

python is a cat.

再说mode,它指定文件打开的模式。

'r': 以只读模式打开(缺省模式,必须保证文件存在)

'w':以只写模式打开。若文件存在,则清空文件,然后重新创建;若不存在,则新建

'a':以追加模式打开。若文件存在,则会追加到文件的末尾;若文件不存在,则新建


常见的mode组合

'r'或'rt': 默认模式,文本读模式

'w'或'wt':以文本写模式打开(打开前文件被清空)

'rb': 以二进制读模式打开

'ab': 以二进制追加模式打开

'wb': 以二进制写模式打开(打开前文件被清空)

'r+': 以文本读写模式打开,默认写的指针开始指在文件开头, 因此会覆写文件

'w+': 以文本读写模式打开(打开前文件被清空)

'a+': 以文本读写模式打开(只能写在文件末尾)

'rb+': 以二进制读写模式打开

'wb+': 以二进制读写模式打开(打开前被清空)

'ab+': 以二进制读写模式打开

喵喵,初看起来,模式很多,但是,它们只是相互组合罢了。建议记住最基本的w、r、a,遇到特殊场景,再翻看一下就好了。


从with语句到上下文管理器

基础部分讲完了,下面是进阶部分。知其然,更要知其所以然。

1、with语句是初学者必会常识

首先,要解释一下为啥前文直接就用了with语句。with语句是读写文件时的优雅写法,这已经默认是Python初学者必会的常识了。如果你还不会,先看看用和不用with语句的对比:

# 不用with语句的正确写法

try:

f = open('test.txt','w')

f.writelines(['python',' is',' a',' cat'])

finally:

if f:

f.close()

# 使用with语句的正确写法

with open('test.txt','w') as f:

f.writelines(['python',' is',' a',' cat'])

因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量是有限的,所以open()方法之后一定要调用close()方法。另外,读写操作可能出现IO异常的情况,所以要加try…finally,保证无论如何,都会调用到close()方法。

这样写万无一失,但是实在繁琐,一不小心还可能漏写或者写错。而with语句会保证调用close(),只需一行代码,简直不要太优雅!所以,with语句是Python初学者必会技能。

2、什么是上下文管理器?

下面,重头戏来了,什么是上下文管理器(context manager)?

上下文管理器是这样一个对象:它定义程序运行时需要建立的上下文,处理程序的进入和退出,实现了上下文管理协议,即在对象中定义了 __enter__() 和 __exit__() 方法。

__enter__():进入运行时的上下文,返回运行时上下文相关的对象,with 语句中会将这个返回值绑定到目标对象。

__exit__(exception_type, exception_value, traceback):退出运行时的上下文,定义在块执行(或终止)之后上下文管理器应该做什么。它可以处理异常、清理现场或者处理 with 块中语句执行完成之后需要处理的动作。

注意enter和exit的前后有两个下划线,Python中自带了很多类似的方法,它们是很神秘又很强大的存在,江湖人常常称其为“黑魔法”。例如,迭代器协议就实现了__iter__方法。

在Python的内置类型中,很多类型都是支持上下文管理协议的,例如file,thread.LockType,threading.Lock等等。

上下文管理器无法独立使用,它们要与with相结合,with语句可以在代码块运行前进入一个运行时上下文(执行_enter_方法),并在代码块结束后退出该上下文(执行__exit__方法)。

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

3、自定义上下文管理器

除了Python的内置类型,任何人都可以定义自己的上下文管理器。下面是一个示例:

class OpenFile(object):

def __init__(self,filename,mode):

self.filename=filename

self.mode=mode

def __enter__(self):

self.f=open(self.filename,self.mode)

self.f.write("enter now\n")

return self.f #作为as说明符指定的变量的值

def __exit__(self,type,value,tb):

self.f.write("exit now")

self.f.close()

return False #异常会被传递出上下文

with OpenFile('test.txt','w') as f:

f.write('Hello World!\n')

最终写入文件的结果是:

enter now

Hello World!

exit now

上下文管理器必须同时提供 __enter__() 和 _exit_() 方法的定义,缺少任何一个都会导致 AttributeError。

上下文管理器在执行过程中可能会出现异常,_exit_() 的返回值会决定异常的处理方式:返回值等于 False,那么这个异常将被重新抛出到上层;返回值等于 True,那么这个异常就被忽略,继续执行后面的代码。__exit()__ 有三个参数(exception_type, exception_value, traceback),即是异常的相关信息。

4、contextlib实现上下文管理器

上例中,自定义上下文管理器的写法还是挺繁琐的,而且只能用于类级别。为了更好地辅助上下文管理,Python 内置提供了 contextlib 模块,进而可以很方便地实现函数级别的上下文管理器。

该模块本质上是通过装饰器(decorators)和生成器(generators)来实现上下文管理器,可以直接作用于函数/对象,而不用去关心 __enter__() 和 __exit()__ 方法的具体实现。

先把上面的例子改造一下,然后我们再对照着解释:

from contextlib import contextmanager

@contextmanager

def open_file(name):

ff = open(name, 'w')

ff.write("enter now\n")

try:

yield ff

except RuntimeError:

pass

ff.write("exit now")

ff.close()

with open_file('test.txt') as f:

f.write('Hello World!\n')

contextmanager是要使用的装饰器,yield关键字将普通的函数变成了生成器。yield的返回值(ff)等于上例__enter__()的返回值,也就是as语句的值(f),而yield前后的内容,分别是_enter_() 和 _exit_() 方法里的内容。

使用contextlib,可以避免类定义、_enter_() 和 __exit()__方法,但是需要我们捕捉可能的异常(例如,yield只能返回一个值,否则会导致异常 RuntimeError),所以try…except语句不能忽略。

成都加米谷大数据培训机构,10月22日大数据开发零基础班(小班教学创始人授课)预报名进行中...

相关推荐

开机进入ghost启动项(电脑启动进入ghost)

电脑启动的时候进入GHOST界面方法:  1、首先确认电脑装了GHOST软件。  2、重启电脑,注意仔细观察电脑屏幕,会有一个3s或者10s的选择界面。让选择是进入GHOST界面,或者正常启动进入系...

华硕bios修复蓝屏图解(华硕bios修复蓝屏视频教程)

先看下BIOS是否可以识别到硬盘设备,若看不到,硬盘故障的可能性很大。若可以看到硬盘,建议先尝试进行BIOS兼容性设置:1,在BIOS界面,通过方向键进【Secure】菜单,通过方向键选择【Sec...

老电脑怎么装win7系统(老电脑装win7系统可以吗)

6年前的电脑,如果是用的当时最新的CPU的话,应该是第7代或者第6代酷睿等级的。运行windows7和windows10都应该没有压力。从软件的兼容性来说,还是建议安装windows10,因为现在有好...

电脑怎么设置到点自动关机(电脑怎样设置到点关机)

1、首先我们点击电脑屏幕左下角的开始按钮,在所有程序里依次选择附件---系统工具,接着打开任务计划程序。2、我们打开任务计划程序后,在最右边的操作框里选择创建基本任务,然后在创建基本任务对话框的名称一...

2025年笔记本电脑排行榜(20201年笔记本电脑推荐)

2023华为笔记本电脑matebook16系列很好用的。因为这个系列她是有非常好的性价,比的是能够让你有非常轻薄的厚度,并且能够有11.6寸的屏幕,而且还有120赫兹的刷新率作为大学生,您可能需要经常...

powerpoint激活密钥(ppt密钥 激活码2010)

1/4进入文件打开一个PPT文件进入到软件界面,在界面左上方找到文件选项,点击该选项进入到文件页面。2/4点击账户文件页面中,页面左侧找到账户选项,点击该选项,页面右侧会出现相应的操作选择。3/4点击...

水星usb无线网卡驱动下载(水星usb无线网卡驱动下载安装)
  • 水星usb无线网卡驱动下载(水星usb无线网卡驱动下载安装)
  • 水星usb无线网卡驱动下载(水星usb无线网卡驱动下载安装)
  • 水星usb无线网卡驱动下载(水星usb无线网卡驱动下载安装)
  • 水星usb无线网卡驱动下载(水星usb无线网卡驱动下载安装)
qq恢复删除好友官网(qq恢复已删好友)
qq恢复删除好友官网(qq恢复已删好友)

qq恢复官方网站,http://huifu.qq.com/1、什么是QQ恢复系统?QQ恢复系统是腾讯公司提供的一项找回QQ联系人、QQ群的服务,向所有QQ用户免费开放。2、QQ恢复系统能恢复多长时间内删除的好友?普通用户可以申请恢复3个月内...

2025-12-28 16:03 off999

优启通u盘重装win7系统教程(优启通u盘装win7系统教程图解)

系统显示未找到万能驱动的解决方法是:1、重插下usb口1、造成“找不到驱动器设备驱动程序”的原因,可能是usb口出现问题。2、换个usb口可能是单独这个usb口出现问题,可以选择另外的usb口重试wi...

笔记本mac地址在哪看(笔记本电脑mac地址怎么查询)
  • 笔记本mac地址在哪看(笔记本电脑mac地址怎么查询)
  • 笔记本mac地址在哪看(笔记本电脑mac地址怎么查询)
  • 笔记本mac地址在哪看(笔记本电脑mac地址怎么查询)
  • 笔记本mac地址在哪看(笔记本电脑mac地址怎么查询)
wifi加密方式怎么设置(wifi网络加密怎么设置)

若你想将自己的无线网改成加密的,可以按照以下步骤操作:1.打开你的路由器管理界面。一般来说,在浏览器地址栏输入“192.168.1.1”或“192.168.0.1”,然后输入用户名和密码登录就可以打...

sql数据库自学(数据库入门必看——《sql基础教程》)

SQLServer数据库基础知识:1.数据库是由数据组成的,这些数据可以被组织成有序的数据结构,以支持特定的应用程序。2.数据库管理系统(DBMS)是一种软件工具,用于创建、管理和操作数据库。...

无线网连接不可上网怎么回事

可能有几下几方面原因:1、无线路由器网络参数设置错误,无法拨通ISP运营商的局端设备,无法接入互联网;2、宽带线路出现故障,路由器无法拨通ISP运营商的局端设备,无法连通;3、宽带DNS服务器由于某种...

电脑蓝屏重新启动(电脑蓝屏重新启动快捷键)
  • 电脑蓝屏重新启动(电脑蓝屏重新启动快捷键)
  • 电脑蓝屏重新启动(电脑蓝屏重新启动快捷键)
  • 电脑蓝屏重新启动(电脑蓝屏重新启动快捷键)
  • 电脑蓝屏重新启动(电脑蓝屏重新启动快捷键)
恢复大师app下载(恢复大师app下载软件)

是真的。开心手机恢复大师是一款苹果手机数据恢复软件,可以恢复删除的微信聊天记录、短信、通讯录、备忘录、qq聊天记录等17种数据。我测试了一下,确实是可以恢复的。而且开心手机恢复大师是可以免费试用的,是...

取消回复欢迎 发表评论: