文件打开操作在 Python 2.7 中行为异常



我正在学习异常,因此执行一些文件操作并测试在处理 Python 文件时可能产生异常的代码的各个部分。我正在Canopy上执行这个Python 2.7代码。

#!/usr/bin/python
import os
try:
fp = open('testfile', 'r')
except IOError:
print 'File not opened successfully'
else:
print 'File opened successfully'
try:
fp.write('Hello!')
except IOError:
print 'Write not allowed on this file'
else:
print 'Write successful'
try:
fp.close()
except IOError:
print 'File not closed properly'
else:
print 'File closed successfully'
finally:
if os.path.exists(fp.name):
os.remove(fp.name)

当我执行此代码时,我得到以下输出:

文件未正确打开

名称错误回溯(最近一次调用(

/home/sr/Python/tcs.py in ((

--> 185 如果 os.path.exists(fp.name(

名称错误: 未定义名称"fp">

但是,如果我将文件的访问模式更改为"w",那么一切似乎都可以正常工作,正确的输出为:

文件打开成功

写入成功

文件已成功关闭

我不明白为什么"r"模式没有使文件正确打开,因此没有创建fp文件对象。请帮我解决问题。

PS:我也想知道是否有更好的方法来实现同样的事情。但这是可选的。

解释

错误与打印输出相结合应该是不言自明的:如果您无法打开文件,变量fp就不存在。

模式'r'指示您要打开文件进行reading。您无法读取不存在的内容,因此在处理IOError后,您最终会转到代码中的finally块。但是错误发生在设置fp之前,所以没有变量fp,因此错误。[以下解决方案]

模式'w'指示您要从头开始打开writing。如果文件已存在,则还有一个 ppend'a'模式。你可以很好地写入一个不存在的文件,这样你的代码就不会失败。事实上,如果文件确实存在于'w'模式下,它将被截断,并且任何以前的内容都将丢失。

尝试创建一个空文件并使用模式'r'运行。您应该得到一个打印'Write not allowed on this file'的异常。这是因为,正如您的错误消息正确指示的那样,不允许写入在读取模式下打开的文件。

改进

您可以对代码进行两项主要改进。一个是修复逻辑缺陷,另一个是使用with语句进行重大的风格改进。

您有两个主要的逻辑错误。第一个是在你已经看到的最外层finally块。最简单的解决方法是将finally块的内容移动到else中,因为如果文件未打开,则无需执行任何操作。另一种解决方案是引用您首先尝试打开的文件名。例如,您可以将文件名存储到变量中并使用它:

filename = 'testfile'
try:
fp = open(filename, 'r')
...
finally:
if os.path.exists(filename):
os.remove(filename)

第二个主要逻辑错误是,如果写入失败,则不会关闭文件。请注意,仅在try块的else子句中调用fp.close()。如果应该出现在finally块中。print声明当然应该留在else。改变

else:
print 'Write successful'
try:
fp.close()
...

else:
print 'Write successful'
finally:
try:
fp.close()
...

通过使用with块来管理文件操作,可以在风格上改进整个代码。执行此操作的明显方法如下:

fname = 'testfile'
with open(fname, 'r') as fp:
fp.write('Hello!')
if os.path.exists(fname):
os.remove(fname)

当事情失败时,您不会收到那么多详细的消息,但总的来说,此代码比您拥有的代码更干净,更短,更健壮。它保证无论在此过程中的任何地方是否发生异常,文件都将关闭。如果您需要当前拥有的详细错误输出,请继续使用当前try块。大多数人更喜欢with的原因是,发生的任何错误都会有一个详细的描述和一个发生的行号,所以你基本上可以用更少的工作获得所有必要的信息。

以下是一些其他资源,可帮助您了解with和上下文管理器:

  • 理解 Python 的 "with" 语句(来自 effbot.org(
  • with的官方文档
  • SO 1, 2, 3, 4

最新更新