python3基础 IO操作

一、IO编程

IO在计算机中指Input/Output,也就是输入和输出由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。

比如你打开浏览器,访问新浪首页,浏览器这个程序就需要通过网络IO获取新浪的网页。浏览器首先会发送数据给新浪服务器,告诉它我想要首页的HTML,这个动作是往外发数据,叫Output,随后新浪服务器把网页发过来,这个动作是从外面接收数据,叫Input。所以,通常,程序完成IO操作会有Input和Output两个数据流当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作

IO编程中,Stream(流)是一个很重要的概念,流的本质其实就是数据传输的通道,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。对于浏览网页来说,浏览器和新浪服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。

由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。举个例子来说,比如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,可是磁盘要接收这100M数据可能需要10秒,怎么办呢?有两种办法:

第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO

另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO

同步和异步的区别就在于是否等待IO执行的结果。好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。

你说“来个汉堡”,服务员告诉你,汉堡需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。

很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。想想看,你得知道什么时候通知你“汉堡做好了”,而通知你的方法也各不相同。如果是服务员跑过来找到你,这是回调模式,如果服务员发短信通知你,你就得不停地检查手机,这是轮询模式。总之,异步IO的复杂度远远高于同步IO。

操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。我们后面会详细讨论Python的IO编程接口。

注意,本章的IO编程都是同步模式,异步IO由于复杂度太高,后续涉及到服务器端程序开发时我们再讨论。

小结:

1.基本概念: input,output, stream

2.存在问题:CPU(内存)和硬盘(网络)的处理速度不匹配

3.IO编程:同步IO、异步IO(回调--好了叫我, 轮询--好了没..好了没)

4.收获新知:编程语言都会把操作系统提供的低级C接口封装起来方便使用。

5. 内存读写速度比硬盘快的多的原因:因为硬盘是机械设备,属于机械存储介质,当读取或写入数据时,必须旋转磁盘以定位所需的数据,并将读写头移动到正确的位置。硬盘需要物理运动来读写数据,需要寻找和移动读写头,这会导致较高的延迟,通常在毫秒级别或更长的时间内完成读写,而内存是电子设备,读写速度非常快,可以在纳秒级别的时间内完成读写操作。另外在读写方式上,内存以随机存取的方式工作,可以直接通过内存地址访问任何数据。这使得内存的读写速度不受数据位置的影响。磁盘则需要按照物理磁道上的顺序读取数据,因此在读取大量非连续数据时会有明显的性能下降。

二 文件IO操作 - 文件读写

示例文件:data.txt 内容如下

abcdefg
higklmn
hello,hello,say hello
你好哦

Python读写文件的方法:

读取文件的对象:

fin = open("data.txt")    # data.txt里有中文的话会报 UnicodeDecodeError

fin = open("data.txt",encoding="utf-8") # 指定字符编码为utf-8可以解决中文报错问题

读取文件的全部内容: whole_data = fin.read()   

按行读取文件的内容:for line in fin: print(line)  # 执行结果每行数据后会自动添加换行符,导致数据之间会自动多一个空行

按行读取文件的内容:for line in fin: print(line.strip())  # 把末尾的'\n'删掉

按行读取文件的内容:for i in fin.readlines(): print(i.strip()) # 把末尾的'\n'删掉

一次读取所有内容并按行返回:fin.readlines()   # 返回结果是一个 List

文件的关闭: fin.close()

示例:

#fin = open("data.txt")
fin = open("data.txt",encoding="utf-8")
print(fin.readlines())
fin.close()

运行结果:

读取文件全部内容示例:

#fin = open("data.txt")
fin = open("data.txt",encoding="utf-8")
whole_data = fin.read()
print(whole_data)
fin.close()

运行结果:

按行读取文件的内容示例:

fin = open("data.txt",encoding="utf-8")
for line in fin: print(line)
fin.close()

运行结果:

按行读取文件的内容示例2:

fin = open("data.txt",encoding="utf-8")
for line in fin: print(line.strip())
fin.close()

或

with open("data.txt", encoding="utf-8") as fin:
    for i in fin.readlines(): print(i.strip())

执行结果:

一次读取所有内容并按行返回示例:

fin = open("data.txt",encoding="utf-8")
print(fin.readlines())
fin.close()

运行结果:

写入文件的对象:fout = open("output-data.txt","w")

写出一行数据到文件: fout.write("hello,word!\n又是美好的一天")

写大文件时刷新内存到文件: fout.flush()

文件的关闭: fout.close()

示例:

fout = open("output-data.txt","w")
fout.write("hello,word!\n又是美好的一天")
fout.close()

fout = open("output-data.txt","wb")
fout.write("hello,word!\n又是美好的一天".encode("utf-8"))
fout.close()

运行结果:

生成了output-data.txt文件,文件内容如下:

注意:读写文件时,如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在:

>>> f=open('/Users/michael/notfound.txt', 'r')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/notfound.txt'

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现:

try:
    f = open('/path/to/file', 'r')
    print(f.read())
finally:
    if f:
        f.close()

但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:

with open('/path/to/file', 'r') as f:
    print(f.read())

这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

其它示例:

input.txt文件内容如下:

读取文件 input.txt 的内容,并求和和平均值并写入到文件 output.txt 中

test.py 写法:

'''
open方法:Open file and return a stream.
文件路径可以用相对路径也可以用绝对路径
如果不指定文件打开模式,则默认为读模式,即 open("input.txt")等价于open("input.txt","r")
'''
fin = open("input.txt")

sum = 0
count = 0

# 使用for循环读取每一行,挨个进行处理
for line in fin:
    # line 肯定是str类型,如果想变成int类型,需要使用int函数强转(可以强转的前提:line必须是数字型字符串)
    # strip()函数用于去掉字符串两头的空格,字符串中间的空格不会被去掉
    number = int(line.strip())
    sum += number
    count += 1
print("sum value:",sum)
print('avg value:',sum/count)

fout = open("output.txt","w")  # 写文件时,文件不必事先存在
# fout.write() 只能接收1个参数,且参数必须为str类型(所以,如果参数为整数或浮点数必须进行强转)
# 写文件默认不会换行,都写在同一行,可以加"\n"进行换行
fout.write("sum value:"+str(sum)+"\n")
fout.write("avg value:"+str(sum/count)+"\n")

fin.close()
fout.close()

test.py执行结果:

ok

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值