2011-10-15 26 views
31
# Open new file to write 
file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    file.write("Hello World!") 
    file.close() 

上面的代码是从函数中剥离。一个用户的系统的报告在行错误:python试试:除了:终于

file.write("Hello World!") 

错误:

AttributeError: 'NoneType' object has no attribute 'write' 

问题是,如果Python是无法打开指定文件,“除了”块执行,它必须 返回,但控制正在转移到抛出给定错误的行。 '文件'变量的值是'无'。

任何指针?

回答

67

您不应该写入finally块中的文件,因为在那里引发的异常将不会被except块捕获。

如果try块发生异常,则执行except bock。 finally总是执行所发生的任何事情。

另外,不应该有任何需要将file变量初始化为none

except块中使用return不会跳过finally块。就其性质而言,它不能被跳过,这就是为什么你要把你的“清理”代码放在那里(即关闭文件)。

所以,如果你想使用尝试:除了:最后,你应该做这样的事情:

try: 
    with open("output", "w") as outfile: 
     outfile.write('Hello World') 
except IOError: 
    print 'oops!' 

try: 
    f = open("file", "w") 
    try: 
     f.write('Hello World!') 
    finally: 
     f.close() 
except IOError: 
    print 'oops!' 

更清洁的这样做是使用with声明的方式

+11

+1'with'声明 – gecco

+0

代码很clever.i从中 – viprs

+1

学习不幸的是,'with'不存在在Python 2.4,所以它不会工作。 – SummerBreeze

0

终于总是在“结束”中被调用,即使异常发生。您可以使用它来确保打开的资源已关闭(例如,数据库连接,文件等)。

我想你误解了语义。

你的逻辑应该在“尝试”中,你应该在“except”块中处理异常,无论你的方法终止如何,“finally”都会执行,用它来清理。

1

除了不执行(因为类型是IOError)它是抛出另一个类型为AttributeError的错误的最后部分,因为file = None。

27

如果文件未打开,则行file = open(filePath, 'w')失败,因此没有任何内容被分配给file

然后,except子句运行,但没有任何文件,所以file.close()失败。

finally子句总是运行,即使有异常。而且由于file仍然是None,你会得到另一个例外。

你想要一个else子句而不是finally,只有在没有异常时才会发生。

try: 
     file = open(filePath, 'w') 
    except IOError: 
     msg = "Unable to create file on disk." 
     return 
    else: 
     file.write("Hello World!") 
     file.close() 

为什么else?该Python docs说:

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.

换句话说,这不会赶上从writeclose呼叫的IOError。这是好的,因为那么原因并不是“无法在磁盘上创建文件” - 它会是一个不同的错误,一个是你的代码没有准备好。不要试图处理这样的错误是个好主意。

+1

+1用于未使用的“else” – kindall

+0

但是如果file.write()引发异常 - 打开后完全可能会发生这种情况尽管它是用写入权限打开的。最好把它包含在try:block中 – jenming

+1

@jenming:好吧,几乎任何东西都可以引发异常:)但是,您应该尽量只处理您期望的异常。如果您担心'file.write()'的异常,则将其包含在'try'中;只要确保不要包含像'file.write(“result:%s”%do_calculation())'这样的东西,因为这会从'do_calculation'中隐藏异常。 –

3

什么是在包括

file.write("Hello World!")

finally子句内部的逻辑??我认为它必须放在try条款本身。

try: 
     file = open(filePath, 'w') 
     file.write("Hello World!") 
except IOError: 
     print("Unable to create file on disk.") 
finally: 
     file.close() 
0

总是建议编写可能在try块中抛出异常的逻辑或代码,并使用finally块关闭资源。

+0

与原始问题无关。 – stackoverflowuser2010

1

你可以做这样的事情:

try: 
    do_some_stuff() 
finally: 
    cleanup_stuff() 
1

这是最直接的解决您的问题。我使用在finally区块中检查file_obj != None的成语。

顺便说一下,你应该知道file是一个Python类名,所以你应该选择一个不同的变量名。

file = None 
try: 
    file = open(filePath, 'w') 
except IOError: 
    msg = ("Unable to create file on disk.") 
    file.close() 
    return 
finally: 
    if file != None: 
     file.write("Hello World!") 
     file.close()