简单语法支撑不起 Python,文件操作却是重中之重。这节我们来探索一下 Python 中内置函数 Open(),让你从此爱上文件操作。

一、简介

Python open() 函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。

二、Open 文件操作

先来一个示例直观感受一下吧,我们打开一个文件,并读取文件内容:

1
2
3
4
5
6
import sys

result = []
with open(r'{}/README.md'.format(sys.path[0]), 'r') as fp:
for line in fp.readlines():
result.append(line)

代码很简单,先创建了一个空数组,然后按行读取文件内容,并存入数组。

存完后,又觉得无聊,我要把读到的内容输出到指定的文件中:

1
2
3
4
import sys

with open('{}/jartto.txt'.format(sys.path[0]),'w') as f:
f.writelines(result);

打开 jartto.txt 文件,将上一步读取到的 result 结果,写入其中。

从头到尾我们貌似做了无用功,但是你却对文件读写操作有了整体的认识。我们继续,是时候解开 PythonOpen() 函数的面纱了!

三、函数语法

要真正理解 Open 方法,我们需要做一些功课:

1
open(name[, mode[, buffering]])

参数说明:

  • name: 一个包含了你要访问的文件名称的字符串值。
  • mode: mode 决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
  • buffering: 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。

关于 mode 这里多说一句:最常用的模式可能是 r 和 w

参数说明:

  • r: 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
  • rb: 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
  • r+: 打开一个文件用于读写。文件指针将会放在文件的开头。
  • rb+: 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
  • w: 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
  • wb: 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
  • w+: 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
  • wb+: 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
  • a: 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • ab: 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • a+: 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
  • ab+: 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

name 和 mode 都不难理解,上文示例已经应用到了,那 buffering 是什么鬼?

四、关于 Buffering

官方解释如下:
The optional buffering argument specifies the file’s desired buffer size: 0 means unbuffered, 1 means line buffered, any other positive value means use a buffer of (approximately) that size. A negative buffering means to use the system default, which is usually line buffered for tty devices and fully buffered for other files. If omitted, the system default is used.

  • Buffering0False ,没有缓冲区;

    1
    2
    3
    4
    import sys

    f = open(r'{}/jartto.txt'.format(sys.path[0]), 'w', False)
    f.write('Jartto\'s blog')

    jartto.txt 文件查看,字符串已被写入文件。

  • 若为 1True 有缓冲区;

    1
    2
    f = open(r'{}/jartto.txt'.format(sys.path[0]), 'w', True) 
    f.write('Jartto\'s blog')

    若缓冲区满了则自动写入文件 jartto.txt 中,否则需要 f.flush() 或 f.close(),才能写入 jartto.txt 文件;

  • 若为其他正数则表示缓冲区大小;

    1
    f = open(r'{}/jartto.txt'.format(sys.path[0]), 'w', 20)

    有缓冲区,缓冲区大小 20 字节。当写入字符串少于 20 字节时,先写入缓冲区,需要 flush()close(),才能写入 jartto.txt 文件;
    当字符串不少于 20 字节时,先写入缓冲区,若缓冲区满了,则自动写入 jartto.txt 文件,依次类推,最后缓冲区中的内容需 f.flushf.close() ,才能写入 jartto.txt 文件;

  • 若为负数,则使用默认缓冲区大小;

    1
    2
    f = open(r'{}/jartto.txt'.format(sys.path[0]), 'w', -1) 
    f.write('Jartto\'s blog')

    先写入缓冲区,若缓冲区满了则自动写入文件 jartto.txt 中,否则需要 f.flush()f.close() 才能写入文件。

这里有个问题,为什么要写入缓冲区,Buffering 是不是可有可无?

在网上查到一个关于缓冲区作用的描述:
FileInputStream/FileOutputStream 每次调用 read()/write() 都会触发一个 IO 操作。
BufferedInputStream/BufferedOutputSteam 调用 read()/write() 并不会每次都触发一个 IO 操作,只是写到内部的buffer里面,而只有内部的 buffer 满了或者调用 flush() 才会触发 IO 操作。

IO 操作越少,性能越好。

操作系统不仅会将硬盘上的文件读到内存作为缓存使用,也会在内存开辟另外一段空间给内存的数据做缓存处理。意义何在?

为了管理,也为了效率。

  • 内存与内存之间的数据交换,比内存与硬盘之间的数据交换速率高了两个数量级。
  • 当内存上的某个进程需要数据的时候,如果内存缓存有匹配的数据,则直接在缓存区取,如果没有,再去硬盘上读。(写也同理)
  • 代码需要进行频繁的IO操作时,意义就体现出来了。

扩展阅读:

五、File 对象方法

Open() 函数从来都不是单用的,它与文件操作密不可分,所以请不要离开,再了解一下 File 对象方法?

  • file.read([size]) size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回””(空字串)
  • file.readline() 返回一行
  • file.readlines([size]) 返回包含size行的列表,size 未指定则返回全部行
  • for line in f: print line #通过迭代器访问
  • f.write(“hello\n”) #如果要写入字符串以外的数据,先将他转换为字符串.
  • f.tell() 返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).
  • f.seek(偏移量,[起始位置]) 用来移动文件指针.
    • 偏移量:单位:比特,可正可负
    • 起始位置:0-文件头,默认值;1-当前位置;2-文件尾
  • f.close() 关闭文件

六、file() 与 open()

两者都能够打开文件,对文件进行操作,也具有相似的用法和参数。但是,这两种文件打开方式却有着本质的区别:

  • file 为文件类,用 file() 来打开文件,相当于这是在构造文件类
  • open() 打开文件,是用 python 的内建函数来操作

又到了留下线索的时候了,下一篇:Python 笔记4 - OS 与 Sys 模块