详解 Python 与文件对象共事的实例
详解Python与文件对象共事的实例
Python有一个内置函数,open,用来打开在磁盘上的文件。open返回一个文件对象,它拥有一些方法和属性,可以得到被打开文件的信息,以及对被打开文件进行操作。
>>>f=open("/music/_singles/kairo.mp3","rb")(1) >>>f(2)>>>f.mode(3) 'rb' >>>f.name(4) '/music/_singles/kairo.mp3'
(1) open方法可以接收三个参数:文件名、模式和缓冲区参数。只有第一个参数(文件名)是必须的;其它两个是可选的。如果没有指定,文件以文本方式打开。这里我们以二进制方式打开文件进行读取。(printopen.__doc__会给出所有可能模式的很好的解释。)
(2) open函数返回一个对象(到现在为止,这一点应该不会使你感到吃惊)。一个文件对象有几个有用的属性。
(3) 文件对象的mode属性告诉你文件以何种模式被打开。
(4) 文件对象的name属性告诉你文件对象所打开的文件名。
1.读取文件
你打开文件之后,你要做的第一件事是从中读取,正如下一个例子所展示的。
>>>f>>>f.tell()(1) 0 >>>f.seek(-128,2)(2) >>>f.tell()(3) 7542909 >>>tagData=f.read(128)(4) -99-DiveIntoPythonhttp://diveintopython.org/ >>>tagData 'TAGKAIRO****THEBESTGOA***DJMARY-JANE*** RaveMix2000http://mp3.com/DJMARYJANE\037' >>>f.tell()(5) 7543037
(1) 一个文件对象维护它所打开文件的状态。文件对象的tell方法告诉你在被打开文件中的当前位置。因为我们还没有对这个文件做任何事,当前位置为0,它是文件的起始处。
(2) 文件对象的seek方法在被打开文件中移动到另一个位置。第二个参数指出第一个参数是什么意思:0表示移动到一个绝对位置(从文件起始处算起),1表示移到一个相对位置(从当前位置算起),还有2表示相对于文件尾的位置。因为我们搜索的MP3标记保存在文件的末尾,我们使用2并且告诉文件对象从文件尾移动到128字节的位置。
(3) tell方法确认了当前位置已经移动了。
(4) read方法从被打开文件中读取指定个数的字节,并且返回含有读取数据的字符串。可选参数指定了读取的最大字节数。如果没有指定参数,read将读到文件末尾。(我们本可以在这里简单地说read(),因为我们确切地知道在文件的何处,事实上,我们读的是最后128个字节。)读出的数据赋给变量tagData,并且当前的位置根据所读的字节数作了修改。
(5) tell方法确认了当前位置已经移动了。如果做一下算术,你会看到在读了128个字节之后,位置数已经增加了128。
2.关闭文件
打开文件消耗系统资源,并且其间其它程序可能无法访问它们(取决于文件模式)。这就是一旦操作完毕就该关闭文件的重要所在。
>>>f>>>f.closed(1) False >>>f.close()(2) >>>f >>>f.closed(3) True >>>f.seek(0)(4) Traceback(innermostlast): -100-DiveIntoPythonhttp://diveintopython.org/ File" ",line1,in? ValueError:I/Ooperationonclosedfile >>>f.tell() Traceback(innermostlast): File" ",line1,in? ValueError:I/Ooperationonclosedfile >>>f.read() Traceback(innermostlast): File" ",line1,in? ValueError:I/Ooperationonclosedfile >>>f.close()(5)
(1) 文件对象的closed属性表示对象是打开还是关闭了文件。在本例中,文件仍然打开着(closed是False)。
(2) 为了关闭文件,调用文件对象的close方法。这样就释放掉你加在文件上的锁(如果有的话),刷新被缓冲的系统还未写入的输出(如果有的话),并且释放系统资源。
(3) closed属性证实了文件被关闭了。
(4) 文件被关闭了,但这并不意味着文件对象不再存在。变量f将继续存在,直到它超出作用域或被手工删除。然而,一旦文件被关闭,操作它的方法就没有一个能使用;它们都会引发异常。
(5) 对一个文件已经关闭的文件对象调用close不会引发异常,它静静地失败。
3.处理 I/O错误
现在你已经足能理解前一章的例子程序fileinfo.py的文件处理代码了。下面这个例子展示了如何安全地打开文件和读取文件,以及优美地处理错误。
try:(1) fsock=open(filename,"rb",0)(2) try: fsock.seek(-128,2)(3) tagdata=fsock.read(128)(4) finally:(5) fsock.close() . . . exceptIOError:(6) pass
(1) 因为打开和读取文件有风险,并且可能引发异常,所有这些代码都用一个try...except块封装。(嘿,标准化的缩近不好吗?这就是你开始欣赏它的地方。)
(2) open函数可能引发IOError异常。(可能是文件不存在。)
(3) seek方法可能引发IOError异常。(可能是文件长度小于128字节。)
(4) read方法可能引发IOError异常。(可能磁盘有坏扇区,或它在一个网络驱动器上,而网络刚好断了。)
(5) 这是新的:一个try...finally块。一旦文件通过open函数被成功地打开,我们应该绝对保证把它关闭,即使是在seek或read方法引发了一个异常时。try...finally块可以用来:在finally块中的代码将
总是被执行,甚至某些东西在try块中引发一个异常也会执行。可以这样考虑,不管在路上发生什么,代码都会被“即将灭亡”地执行。
(6) 最后,处理我们的IOError异常。它可能是由调用open、seek或read引发的IOError异常。这里,我们其实不用关心,因为将要做的事就是静静地忽略它然后继续。(记住,pass是一条不做任何事的Python语句。)这样完全合法,“处理”一个异常可以明确表示不做任何事。它仍然被认为处理过了,并且处理将正常继续,从try...except块的下一行代码开始。
4.写入文件
正如你所期待的,你也能用与读取文件同样的方式写入文件。有两种基本的文件模式:
•追加(Append)模式将数据追加到文件尾。
•写入(write)模式将覆盖文件的原有内容。
如果文件还不存在,任意一种模式都将自动创建文件,因此从来不需要任何复杂的逻辑:“如果log文件还不存在,将创建一个新的空文件,正因为如此,你可以第一次就打开它”。打开文件并开始写就可以了。
>>>logfile=open('test.log','w')(1) >>>logfile.write('testsucceeded')(2) >>>logfile.close() >>>printfile('test.log').read()(3) testsucceeded >>>logfile=open('test.log','a')(4) -102-DiveIntoPythonhttp://diveintopython.org/ >>>logfile.write('line2') >>>logfile.close() >>>printfile('test.log').read()(5) testsucceededline2
(1) 你可以大胆地开始创建新文件test.log或覆盖现有文件,并为写入目的而打开它。(第二个参数"w"的意思是为文件写入而打开。)是的,它和想象中的一样危险。我希望你不要关心文件以前的内容,因为它现在已经不存在了。
(2) 你可以使用open返回的文件对象的write方法向一个新打开的文件添加数据。
(3) file是open的同义语。这一行语句打开文件,读取内容,并打印它们。
(4) 碰巧你知道test.log存在(因为你刚向它写完了数据),所以你可以打开它并向其追加数据。("a"参数的意思是为追加目的打开文件。)实际上即使文件不存在你也可以这样做,因为以追加方式打开一文件时,如果需要的话会创建文件。但是追加操作从不损坏文件的现有内容。
(5) 正如你所看到的,原来的行和你以追加方式写入的第二行现在都在test.log中了。同时注意两行之间并没包含回车符。因为两次写入文件时都没有明确地写入回车符,所以文件中没有包含回车符。你可以用"\n"写入回车符。因为你没做这项工作,所以你写到文件的所有内容都将显示在同一行上。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!