导航: 起始页 > Dive Into Python > 异常和文件处理 > 与文件对象共事 | << >> | ||||
Python 研究(Dive Into Python)Python 从新手到高手 [DIP_5_4_CPUG_RELEASE] |
Python 有一个内置函数,open,用来打开在磁盘上的文件。open 返回一个文件对象,它拥有一些方法和属性,可以得到打开文件的信息,和对打开文件进行操作。
>>> f = open("/music/_singles/kairo.mp3", "rb") >>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.mode 'rb' >>> f.name '/music/_singles/kairo.mp3'
open 方法可以接收三个参数:文件名,模式,和缓冲区参数。只有第一个参数,文件名,是必须的;其它两个是 可选的。如果没有指定,文件以文本方式打开。这里我们以二进制方式打开文件进行读取。(print open.__doc__ 会给出所有可能模式的很好的解释。) | |
open 函数返回一个对象 (到现在为止,这一点应该不会使你感到吃惊)。一个文件对象有几个有用的属性。 | |
文件对象的 mode 属性告诉你文件以何种模式被打开。 | |
文件对象的 name 属性告诉你文件对象所打开的文件名。 |
你打开文件之后, 你要做的第一件事是从中读取, 正如下一个例子所显示的。
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.tell() 0 >>> f.seek(-128, 2) >>> f.tell() 7542909 >>> tagData = f.read(128) >>> tagData 'TAGKAIRO****THE BEST GOA ***DJ MARY-JANE*** Rave Mix 2000http://mp3.com/DJMARYJANE \037' >>> f.tell() 7543037
打开文件消耗系统资源, 并且依赖于文件模式, 其它程序或许不能访问它们。这就是一旦操作完毕就该关闭文件的重要所在。
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed False >>> f.close() >>> f <closed file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed True >>> f.seek(0) Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.tell() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.read() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.close()
文件对象的 closed 属性表示对象是否打开或关闭了文件。在本例中,文件仍然打开着 (closed 是 False)。打开文件要消耗系统资源,并且根据文件模式,其它程序可能不能使用它们。一旦你处理完它们,把文件关闭这一点很重要。 | |
为了关闭文件,调用文件对象的 close 方法。这样就释放掉你加在文件上的锁 (如果有的话),刷新被缓冲的系统确实还未写入的输出 (如果有的话),并且释放系统资源。 | |
closed 属性证实了文件被关闭了。 | |
只是因为文件被关闭,并不意味着文件对象停止存在。变量 f 将继续存在,直到它 超出作用域 或被手工删除。然而,一旦文件被关闭,可操作打开文件的方法没有一个能使用;它们都会引发异常。 | |
对一个文件已经关闭的文件对象调用 close 不会 引发异常,它静静地失败。 |
现在你已经足能理解前一章的例子程序 fileinfo.py 的文件处理代码了。 下面这个例子展示了如何安全的打开文件和读取文件以及优美地处理错误。
try: fsock = open(filename, "rb", 0) try: fsock.seek(-128, 2) tagdata = fsock.read(128) finally: fsock.close() . . . except IOError: pass
因为打开和读取文件有风险,并且可能引发异常,所有这些代码都用一个 try...except 块封装。(嘿,标准化的缩近 不好吗?这就是你开始欣赏它的地方。) | |
open 函数可能引发 IOError 异常。(可能是文件不存在。) | |
seek 方法可能引发 IOError 异常。(可能是文件长度小于 128 字节。) | |
read 方法可能引发 IOError 异常。(可能磁盘有坏扇区,或它在一个网络驱动器上,而网络刚好断了。) | |
这是新的:一个 try...finally 块。一旦文件通过 open 函数被成功地打开,我们应该绝对保证把它关闭,甚至由于 seek 或 read 方法引发了一个异常。try...finally 块可以用来:在 finally 块中的代码将 总是 被执行,甚至某些东西在 try 块中引发一个异常也会执行。可以这样考虑,不管在路上发生什么,代码都会被 “即将灭亡” 地执行。 | |
最后,处理我们的 IOError 异常。它可能是由调用 open, seek 或 read 引发的 IOError 异常。这里,我们其实不用关心,因为将要做的事就是静静地忽略它然后继续。(记住,pass 是一条不做任何事的 Python 语句。) 这样完全合法,“处理” 一个异常可以明确表示不做任何事。它仍然被认为处理过了,并且处理将正常继续,从 try...except 块的下一行代码。 |
正如你所期待的, 你也能用与读取文件同样的方式写入文件。 有两种基本的文件模式:
如果文件还不存在, 任意一种模式都将自动创建文件, 因此从来不需要任何复杂的逻辑 "如果 log 文件还不存在, 将创建一个新的空文件,正因为如此,你可以第一次就打开它" 。 打开文件并开始写就可以了。
>>> logfile = open('test.log', 'w') >>> logfile.write('test succeeded') >>> logfile.close() >>> print file('test.log').read() test succeeded >>> logfile = open('test.log', 'a') >>> logfile.write('line 2') >>> logfile.close() >>> print file('test.log').read() test succeededline 2
<< 异常和文件处理 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
for 循环 >> |