您在这里:首页 > 深入 Python > 异常和文件处理 > 使用文件对象 | << >> | ||||
深入 Python从 Python 新手到专业人士 |
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.closedFalse >>> 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 块之后的下一行代码处正常继续。 |
如您所料,您也可以写入文件,其方式与从中读取文件的方式大致相同。有两种基本的文件模式
如果文件不存在,则任一模式都会自动创建文件,因此永远不需要任何诸如“如果日志文件尚不存在,则创建一个新的空文件,以便您可以第一次打开它”之类的繁琐逻辑。只需打开它并开始编写即可。
>>> 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 循环进行迭代 >> |