Python 2.7 中的文件打开操作行为异常
File opening operation misbehaving in 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)
当我执行这段代码时,我得到以下输出:
File not opened properly
NameErrorTraceback (most recent call last)
/home/sr/Python/tcs.py in ()
--> 185 if os.path.exists(fp.name)
NameError: name 'fp' is not defined
但是,如果我将文件的访问模式更改为 'w',那么一切似乎都可以正常工作,正确的输出如下:
File opened successfully
Write successful
File closed successfully
我无法理解为什么 'r' 模式无法正确打开文件,因此无法创建 fp 文件对象。请帮我解决问题。
P.S.: 另外我想知道是否有更好的方法来实现同样的事情。但这是可选的。
说明
结合您的打印输出的错误应该是不言自明的:如果您无法打开文件,变量 fp
不存在。
模式'r'
表示您要打开文件进行r阅读。您无法读取不存在的内容,因此在处理 IOError
之后,您最终会转到代码中的 finally
块。但是错误发生在 fp
被设置之前,所以没有变量 fp
,因此错误。 [以下解决方案]
模式 'w'
表示您想要打开 writing,但要从头开始。如果文件已经存在,还有一个 'a'
模式可以 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 中的文件时可能产生异常的代码的各个部分。我正在 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)
当我执行这段代码时,我得到以下输出:
File not opened properly
NameErrorTraceback (most recent call last)
/home/sr/Python/tcs.py in ()
--> 185 if os.path.exists(fp.name)
NameError: name 'fp' is not defined
但是,如果我将文件的访问模式更改为 'w',那么一切似乎都可以正常工作,正确的输出如下:
File opened successfully
Write successful
File closed successfully
我无法理解为什么 'r' 模式无法正确打开文件,因此无法创建 fp 文件对象。请帮我解决问题。
P.S.: 另外我想知道是否有更好的方法来实现同样的事情。但这是可选的。
说明
结合您的打印输出的错误应该是不言自明的:如果您无法打开文件,变量 fp
不存在。
模式'r'
表示您要打开文件进行r阅读。您无法读取不存在的内容,因此在处理 IOError
之后,您最终会转到代码中的 finally
块。但是错误发生在 fp
被设置之前,所以没有变量 fp
,因此错误。 [以下解决方案]
模式 'w'
表示您想要打开 writing,但要从头开始。如果文件已经存在,还有一个 'a'
模式可以 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
和上下文管理器: