python的IO操作

IO操作

IO也就是我们说的Input/Output,也就是输入和输出。我们的程序在运行过程中所有的数据都是驻留在内存当中,有的时候我们需要将内存的数据写到磁盘中,这时候就要用到磁盘IO,有的时候我们需要网络和其他应用程序或者服务进行数据交换,这时候就要用到网络IO。

IO无处不在,比如你要访问一个网页,首先你要打开浏览器,输入www.unionsmart.cn 这样的域名地址,然后浏览器会发起一个请求到服务器,这个请求就是网络IO,服务器同样通过网络IO收到请求,然后解释你的请求,然后把你要的网页从磁盘上读出来也就是磁盘IO,然后把文件的内容再通过网络IO返回到用户的浏览器,浏览器通过网络IO接受数据然后展现在我们的页面上。从上面来看IO无处不在。所以我们就来讲讲IO操作。

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

另外IO有两种模式,一种是同步IO,一种是异步IO。同步IO和异步IO的区别在于是否等待IO操作的结果,因为IO操作由于受到硬件的瓶颈,相比于CPU和内存的处理速度要慢的多,这时候CPU干什么,无非是两种,一种是CPU等着,程序暂停执行我们称之为阻塞,知道IO操作结束,然后再继续执行。另外一种是CPU和程序不等着,继续处理其他的内容,IO操作结束通知CPU,CPU再来处理这部分内容。这时候就是不阻塞。

打个比方就是好比你去餐厅点餐,你说“来个包子”,服务员告诉你,对不起,包子要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。你说“来个包子”,服务员告诉你,包子需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。

很明显使用异步IO效率上要比同步IO的效率要高。

异步IO我们又分为两种,还拿买包子来说,包子好了,服务员来通知你包子好了,这是回调模式,如果服务员发短信通知你,你需要不停地检查手机来知道包子是否做好啦,这就是轮训模式。这里我们先讲讲几种常用的IO操作。

文件操作

文件操作是最常见的IO操作之一,和其他编程语言一样Python也内置了文件操作的函数。

在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,几乎所有的高级语言的读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符或文件句柄),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

打开文件

所有的文件操作之前我们都要打开文件也就是我们上面说的文件句柄或文件描述符,后面我们统一为文件对象。Python我们通过内置函数open()来打开一个文件,这个函数返回的就是文件对象。

>>> f = open('test.txt')
>>> f
<_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>

open()至少有一个参数,也就是我们要打开的文件名(绝对路径和相对路径都可以),默认情况是以只读的方式打开的也就是'r'的模式打开。需要注意的是以读的形式打开文件,要打开的文件一定要存在,如果不存在会抛出异常,以写也就是'w'或追加'a'的模式打开的文件,如果文件不存在会自动帮你创建文件,但前提是文件所在的目录一定要存在,如果不存在也同样会报错。所以,建一个各位在打开文件之前一定要先判断一下文件是否存在。不存在报错退出或执行相关操作。

读文件

如果文件成功打开,我们就可以调用文件对象的read()方法读取文件的内容。

>>> f.read()
'hello\n'

注意:和我们的数据库一样,文件也要有个类似游标的东西标识文件对象当前的位置,另外read()还可以指定一个参数表示一次读取的长度(单位字节),默认传参的情况下,是读取文件的全部到内存中,所以当我们f.read()的时候游标浮动到文件的结尾,所以当我们在调用read()方法的时候,就什么都读不出来了。将会返回一个空字符串。

>>> f.read()
''

如果我们需要重新读取文件内容,一种方式先关闭文件,然后从新打开。另外一种方式是调用文件对象的seek(0)把游标浮动到文件开头,或指定位置。

>>> f.seek(0)
0
>>> f.read()
'hello\n'

除了read(),我们还可以调用readline()函数一行一行的读取文件的内容,直到最后返回空字符串。

>>> f.readline()
'hello\n'
>>> f.readline()
''

另外我们还以调用文件对象的readlines()方法读取文件,这个方法返回的是一个列表,文件的每一行就是这个列表的一个元素。

>>> f.readlines()
['hello\n']
>>> f.readlines()
[]

写文件

通常我们写文件有两种,一种是整个新进去,这时候文件会被整体覆盖也就是用'w'的模式打开文件。另一种是一行一行的或者说是一部分一部分的写,每次写都是在文件最后面追加进去也就是'a'模式。往文件里写东西我们一般就用write()方法就够用了

>>> f = open('test.txt', 'w')
>>> f.write('hello too')
9

write()方法返回写进去的字符数,另外需要注意的是以'w'打开文件的一瞬间,文件的内容就已经被清空了,即便我们只是打开了。所以一定要注意。而以'r'模式则不同,它本身不会覆盖文件,而且游标回跳到文件末尾,每次写东西只是追加进去。

关闭文件

当我们执行完文件操作后一定要及时关闭文件,关闭文件我们用文件对象的close()方法就可以了。

>>> f.close()

文件操作的异常处理和with-as表达式

由于文件操作会经常遇到各种异常,所以我们一定要在执行文件操作的时候进行异常捕获,保证整个程序的健壮性。我们以读文件为例:

try:
    f = open('test.txt', 'r')
except:
    pass
    exit(-1)
try:
    print(f.read())
except:
    pass
finally:
    f.close()

说明:为什么要写finally,这是因为这是为了当文件操作遇到异常的时候保证文件能正常关闭。pass表示执行一些必要操作,比如输出错误,写入日志等。

另外Python从2.5之后支持with-as表达式,可以保证我们在文件操作出现部分异常的时候保证关闭文件,所以上面的代码我们可以通过with-as表达式简写成这样

try:
    with open('test.txt', 'r') as f :
        print(f.read())
except xxxError:
    pass


猜你喜欢

转载自blog.csdn.net/c123_sensing/article/details/81629799