9.2 文件内建函数(open()和file())
作为打开文件之门的“钥匙”,内建函数open()[以及file()]提供了初始化输入/输出(I/O)操作的通用接口。open()内建函数成功打开文件后时候会返回一个文件对象,否则引发一个错误。当操作失败, Python会产生一个IOError异常——我们会在下一章讨论错误和异常的处理。内建函数open()的基本语法是:
file_name是包含要打开的文件名字的字符串,它可以是相对路径或者绝对路径。可选变量 access_mode也是一个字符串,代表文件打开的模式。通常,文件使用模式‘r’,‘W’,或是‘a’模式来打开,分别代表读取,写入和追加。还有个‘U’模式,代表通用换行符支持(见下)。
使用‘r’或‘U’模式打开的文件必须是已经存在的。使用‘W’模式打开的文件若存在则首先清空,然后(重新)创建。以‘a’模式打开的文件是为追加数据作准备的,所有写入的数据都将追加到文件的末尾。即使你seek到了其他的地方。如果文件不存在,将被自动创建,类似以“W”模式打开文件。如果你是一个C程序员,就会发现这些也是C库函数fopen()中使用的模式。
其他fopen()支持的模式也可以工作在Python的open()下。包括‘+’代表可读可写,‘b’代表二进制模式访问。关于‘b’有一点需要说明,对于所有POSIX兼容的Unix系统(包括Linux)来说,‘b’是可有可无的,因为它们把所有的文件当作二进制文件,包括文本文件。下面是从Linux手册的fopen()函数使用中摘录的一段,Python语言中的open()函数就是从它衍生出的。
指示文件打开模式的字符串中也可以包含字符“b”,但它不能作为第一个字符出现。这样做的目的是为了严格地满足ANSI C3.159-1989(即ANSI C)中的规定;事实上它没有任何效果,所有POSIX兼容系统,包括Linux,都会忽略“b”(其他系统可能会区分文本文件和二进制文件,如果你要处理一个二进制文件,并希望你的程序可以移植到其他非Unix的环境中,加上“b”会是不错的主意)。
你可以在表9.1中找到关于文件访问模式的详细列表,包括‘b’的使用——如果你选择使用它的话。如果没有给定access_mode,它将自动采用默认值‘r’。
另外一个可选参数buffering用于指示访问文件所采用的缓冲方式。其中0表示不缓冲,1表示只缓冲一行数据,任何其他大于1的值代表使用给定值作为缓冲区大小。不提供该参数或者给定负值代表使用系统默认缓冲机制,既对任何类电报机(tty)设备使用行缓冲,其他设备使用正常缓冲。一般情况下使用系统默认方式即可。
这里是一些打开文件的例子:
9.2.1 工厂函数file()
在Python 2.2中,类型和类被统一了起来,这时加入了内建函数file()。当时,很多内建类型没有对应的内建函数来创建对象的实例,例如dict()、bool()、file()等。然而,另一些却有对应的内建函数,例如list()、str()等。
open()和file()函数具有相同的功能,可以任意替换。您所看到任何使用open()的地方,都可以使用file()替换它。
可以预见,在将来的Python版本中,open()和file()函数会同时存在,完成相同的功能。一般说来,我们建议使用open()来读写文件,在您想说明您在处理文件对象时使用file(),例如if instance(f, file)。
9.2.2 通用换行符支持(UNS)
在下一个核心笔记中,我们将介绍如何使用OS模块的一些属性来帮助你在不同平台下访问文件,不同平台用来表示行结束的符号是不同的,例如\n,\r,或者\r\n。所以,Python的解释器也要处理这样的任务,特别是在导入模块时分外重要。你难道不希望Python用相同的方式处理所有文件吗?
这就是UNS(Universal NEWLINE Support,通用换行符支持)的关键所在,作为PEP 278的结果,Python 2.3引入了UNS。当你使用‘U’标志打开文件的时候,所有的行分隔符(或行结束符,无论它原来是什么)通过Python的输入方法(例如read*())返回时都会被替换为换行符NEWLINE(\n)。(‘rU’模式也支持‘rb’选项)。这个特性还支持包含不同类型行结束符的文件。文件对象的newlines属性会记录它曾“看到的”文件的行结束符。
如果文件刚被打开,程序还没有遇到行结束符,那么文件的newlines为None。在第一行被读取后,它被设置为第一行的结束符。如果遇到其他类型的行结束符,文件的newlines会成为一个包含每种格式的元组。注意UNS只用于读取文本文件。没有对应的处理文件输出的方法。
在编译Python的时候,UNS默认是打开的。如果你不需要这个特性,在运行configure脚本时,你可以使用—without-universal-newlines开关关闭它。如果你非要自己处理行结束符,请查阅核心笔记,使用os模块的相关属性。