如何在Python中测试file.read()错误?

4

我有下面这段代码(改编自Dive Into Python中的一个例子),它将文件的全部内容读入缓冲区。

buffer = ""

try:
    file = open(postFileName, 'rU')
    try:
        # Read the entire POST log file into a buffer
        buffer += file.read()
    finally:
        file.close()
except IOError:
    buffer += "The POST file could not be opened."

这段代码让我感到困扰的是内部try/finally块没有except块。我需要在这里加一个except块吗?调用read()函数是否可能在调用open()成功后失败?我知道现在try-except-finally已经统一了,所以至少从语法上添加一个except块不是问题。
如果我添加一个except块,在什么条件下它会被执行,如何编写测试来确保在这些条件下运行?
此外,如果我不需要except块,那么为什么需要内部try/finally块呢?
3个回答

7
我发现finally块经常被过度使用。文件关闭(以及其他几个类似的模式)非常重要,以至于Python 3.0将有一个with语句来稍微不那么晦涩地覆盖这个基础。
  • 我需要在finally中使用except吗?

    这个问题涉及到一个具体示例的混乱性质,以及为什么他们添加了with语句。 finally执行“无论如何”清理。无论是否发生异常,finally都会被执行。

  • 在open()成功调用后,read()的调用是否可能失败?

    所有操作系统调用、所有I/O调用(几乎所有内容)都可能引发异常。在打开和读取之间,所有种类的坏事情都可能发生。

  • 如果我添加一个except块,在什么条件下它会被执行?

    查阅文件。在打开和读取之间可能会出现许多怪异的I/O错误。此外,还要查阅内置异常。https://docs.python.org/2/library/exceptions.html

  • 如何编写一个测试来确保它在这些条件下运行?

    你需要一个模拟文件对象。这个对象将响应open但在每个read时引发IOErrorOSError

  • 如果我不需要except块,那么我为什么需要内部的try/finally块?

    清理。无论引发什么异常,finally都将被执行。

尝试一下。看看它会做什么。

try:
 raise OSError("hi mom")
finally:
 print "Hmmm"

感谢您回答了我问题的每一个部分,非常有帮助。 - Bill the Lizard

3
我不同意其他回答中提到统一try / except / finally块的做法。这会改变行为,因为如果打开失败,您不希望finally块尝试关闭文件。在此处使用分离块是正确的(虽然最好使用新的“with open(filename,'rU')as f ”语法)。
read()失败有原因。例如,数据可能太大而无法放入内存,或者用户可能使用control-C发出了中断信号。这些情况不会被IOError捕获,而是留给调用者处理(或不处理),因为调用者可能想根据应用程序的性质执行不同的操作。 但是,即使代码没有处理错误,它仍然有义务清理文件,因此finally块没有except。

谢谢。您对文件成功打开后读取可能失败的解释很有帮助。 - Bill the Lizard

0

使用最新版本的Python,您不需要嵌套try-except和try-finally。try-except-finally已经统一:

try:
  non_existing_var
except:
  print 'error'
finally:
  print 'finished'

谢谢,但我已经知道了 try/except/finally 语法(其实我不知道它们曾经是分开的)。我的问题实际上是关于如何测试 file.read() 失败以确保 except 块在正确(错误?)的条件下运行。 - Bill the Lizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接