Python -- I/O编程
Posted bravesunforever
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python -- I/O编程相关的知识,希望对你有一定的参考价值。
I/O编程
Input/Output 输入/输出
Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水
Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去
由于CPU和内存的速度远远高于外设的速度,所以,在I/O编程中,存在速度严重不匹配的问题。例子:比如要把100M的数据写入磁盘(这是output),CPU输出100M只需要0.01s,可是磁盘要接收这100M数据可能需要10s,怎么办呢?有两种解决方法:
第一种:CPU等着,这种模式称为同步IO
第二种:CPU不等着,这种模式称为异步IO
同步和异步的区别:在于是否等待IO执行的结果.
例子:好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等待5分钟, 有两种处理方式:
(1)你站在收银台前等了5分钟,拿到汉堡再去逛商场,这是同步IO
(2)你先逛商场,等做好了,服务员再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO
结论:很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。而服务员如何通知你汉堡做好了,方法各不相同。
(1) 如果是服务员跑过来找你,这是回调模式
(2)如果服务员发短信通知你,你就要不停地检查手机,这是轮询模式
总之,异步IO的复杂度远远高于同步IO
操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外
文件读写
读文件(read)和写文件(write)
注意:由于“ \\ ”是字符串中的转义符,所以表示路径时,使用“ \\\\ ”或者 “ / ”或者“ \\\\ ”
Python对文本文件和二进制文件采用统一的操作步骤,即“ 打开 - 操作 - 关闭”
读写文件的模式说明:
访问模式 | 说明 |
r | 默认模式,以只读方式打开文件,文件的指针将会放在文件的开头。如果文件不存在,返回异常FileNotFoundError |
w | 打开一个文件只用于写入。如果文件已存在,则将其覆盖。如果文件不存在,创建新文件 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也即是,新的内容会被追加到已有内容之后。如果文件不存在,创建新文件进行写入。 |
x | 创建写模式,文件不存在则创建,存在则返回异常FileExistsError |
t | 文本文件模式,默认值 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。 |
wb | 以二进制格式打开,……(其余的与相应模式的用法相同) |
ab | 以二进制格式打开,……(其余的与相应模式的用法相同) |
+ | 与r/w/x/a/rb/wb/ab一同使用,在原功能基础上,使其同时具有读写功能 |
b | 二进制文件模式 |
注意:(追加append)
open( )函数:打开一个文件对象
格式:open( 文件名,文件模式)
文件模式:“r”模式表示读取utf-8编码的文本文件; “rb”模式表示读取二进制文件
文件模式:“w”模式表示写文本文件;“wb”模式表示写二进制文件
字符编码:
读取非utf-8编码的文本文件,使用encoding参数,
文本文件夹杂一些非法编码的字符时,遇到这种情况,open()函数使用errors参数,表示如果遇到编码错误后如何处理,最简单的方式是直接忽略。
f = open(‘/Users/michael/notfound.txt‘, ‘rb‘,encoding=‘gbk‘,errors=‘ignore‘)
读文件——文件存在
如果文件成功打开,读取文件的方式:
read( )方法:一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示;如果文件有10G,内存就爆了,所以保险起见,可以反复调用read(size)方法。
read(size)方法:每次最多读取size个字节的内容。
readline( ):每次读取一行内容
readlines( ):一次读取所有内容并按行返回一个列表list,列表中的每一个元素为文件中的每一行数据。同时,每一个元素结尾都带一个 \\n标志。
readlines(h):参数可选,如果给出,读入h行
close( )方法
文件使用完毕后必须关闭,有两方面原因:
(1)文件对象会占用操作系统的资源。 (2)操作系统同一时间能打开的文件数量也是有限的。
为了保证无论是否出错都能正确地关闭文件,有两种实现方式:
(1)使用try ... finally
来实现,因为finally语句块一定会被执行。
(2)with
语句:是因为with
语句能自动调用close( )方法
使用try ... finally
来实现:
1 try:
2 f = open(‘/path/to/file‘, ‘r‘)
3 print(f.read())
4 finally:
5 if f:
6 f.close()
with语句:
1 with open(‘/path/to/file‘, ‘r‘) as f:
2 print(f.read())
这和前面的try ... finally
是一样的,但是代码更佳简洁,并且不必调用f.close()
方法。
读文件——文件不存在
如果文件不存在,ope( )函数会抛出一个IOError错误,并且给出错误码和详细的信息告诉你文件不存在:
1 f = open(‘/Users/michael/notfound.txt‘, ‘r‘)
运行结果:
写文件
当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
只有调用close( )方法时,操作系统才保证把没有写入的数据全部写入磁盘。
忘记调用close( )的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:
with open(‘/Users/michael/test.txt‘, ‘w‘) as f:
f.write(‘Hello, world!‘)
文件的定位读写
背景:在实际开发中,可能会需要从文件的某个特定位置开始读写。此时,需要对文件的读写位置进行定位。
两种定位方式:
(1)获取文件当前的读写位置:tell( )方法
(2)定位到文件的指定读写位置:seek (offset, whence )方法
1、使用tell方法来获取文件当前的读写位置
tell方法返回文件的当前位置,即文件指针当前位置
f=open("theima.txt","r")
str=f.read(4)
print("读取的数据是:",str)
#查找当前位置
position=f.tell()
print("当前文件位置:",position)
2、使用seek方法定位到文件的指定读写位置
格式: seek( offset [ , whence ] )
offset:偏移量,即需要移动的字节数
whence表示方向,有三个值:
(1)SEEK_SET或者0:默认值,表示从文件的起始位置开始偏移
(2)SEEK_CUR或者1:表示从文件的当前位置开始偏移
(3)SEEK_END或者2:表示从文件末尾开始偏移
文件的重命名和删除
Python的os模块默认已包含了这些功能
文件的重命名
os模块的rename方法: os.rename( src, dst )
src:需要修改的文件名, dst :修改后的新文件名
文件的删除
os模块的remove方法: os.remove( path )
path:指定路径下的文件
import os
os.rename("毕业论文.txt","毕业论文-最终版.txt")
os.remove("毕业论文.txt")
文件夹的相关操作
创建文件夹
os模块的mkdir方法
import os
os.mkdir("张三")
获取当前目录
os模块的getcwd方法
import os
os.getcwd()
改变默认目录
os模块的chdir方法
例如,将当前目录改编为上一级目录
import os
os.chdir("../")
获取目录列表
os模块的listdir方法
例如,获取当前路径下的子目录列表
import os
os.listdir("./")
删除文件夹
os模块的rmdir方法
例如,删除当前路径下的“张三”目录
import os
os.rmdir("张三")
StringIO和BytesIO
StringIO和BytesIO是在内存中操作str 和bytes(注意:加了s)的方法,使得和读写文件具有一致的接口。
getvalue( )方法用于获得写入write后的值
StringIO
数据读写不一定是文件,也可以在内存中读写。
StringIO就是在内存中读写str
要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可:
1 from io import StringIO 2 3 f=StringIO() 4 f.write(‘Hello‘) 5 f.write(‘ , ‘) 6 f.write(‘World‘) 7 print(f.getvalue())
要读取StringIO,可以用一个str初始化StringIO,然后,像读文件一样读取:
1 # read from StringIO: 2 from io import StringIO 3 f = StringIO(‘水面细风生,\\n菱歌慢慢声。\\n客亭临小市,\\n灯火夜妆明。‘) 4 while True: 5 s=f.readline() 6 if s=="": 7 break 8 print(‘start to print:‘) 9 print(s.strip())
运行结果: 可以看出是一行一行打印出来的
BytesIO
StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:
注意:1、utf-8编码,使用的是encode参数,中间是英文句号点(.)
2、写入的不是str,而是经过UTF-8编码的bytes。
1 from io import BytesIO 2 3 f=BytesIO() 4 f.write(‘中文‘.encode(‘utf-8‘)) 5 print(f.getvalue())
和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:
1 from io import BytesIO 2 f=BytesIO(b‘\\xe4\\xb8\\xad\\xe6\\x96\\x87‘) 3 print(f.read())
以上是关于Python -- I/O编程的主要内容,如果未能解决你的问题,请参考以下文章