让我感到羞愧的是,我不知道如何处理python"with"语句的异常。如果我有代码:
with open("a.txt") as f:
print f.readlines()
我真的想处理"找不到文件的异常"来做一些事情。但我不会写字
with open("a.txt") as f:
print f.readlines()
except:
print 'oops'
不能写
with open("a.txt") as f:
print f.readlines()
else:
print 'oops'
在try/except语句中封闭"with"不起作用,否则:不会引发异常。我该怎么做才能以一种Python般的方式处理"with"语句中的失败呢?
在try/except语句中"enclonding"with"不起作用,否则:不会引发异常"是什么意思?with语句不会神奇地破坏周围的try...except语句。
有趣的是,Java的Test-RealRealSt声明确实支持了你想要的用例。docs.oracle.com/javase/tutorial/essential/exceptions/…
from __future__ import with_statement
try:
with open("a.txt" ) as f :
print f.readlines()
except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available
print 'oops'
如果希望对打开的调用与工作代码中的错误进行不同的处理,可以执行以下操作:
try:
f = open('foo.txt')
except IOError:
print('error')
else:
with f:
print f.readlines()
如stackoverflow.com/questions/5205811/…中所述,这里的try块实在太宽了。在创建上下文管理器和WITH语句体中的异常之间没有区别,因此它可能不是所有用例的有效解决方案。
@但是您可以在with中添加额外的try...except块,以更接近与open()无关的异常的来源。
@Rbaleksandar如果我记得正确的话,我的评论严格地引用了答案中的第一个例子,其中整个with语句都在try/except块中(因此,即使您有内部的try/expect块,它们让escape的任何异常仍然会击中外部的块)。道格拉斯随后又增加了第二个例子来处理那些区分重要的案例。
在这个例子中,文件会被关闭吗?我问是因为它是在"with"范围之外打开的。
@MikeCollins退出"with"将关闭打开的文件,即使该文件在"with"之前打开。
利用with语句,最好的"pythonic"方法列为PEP 343中的示例6,给出了语句的背景。
@contextmanager
def opened_w_error(filename, mode="r"):
try:
f = open(filename, mode)
except IOError, err:
yield None, err
else:
try:
yield f, None
finally:
f.close()
使用方法如下:
with opened_w_error("/etc/passwd","a") as (f, err):
if err:
print"IOError:", err
else:
f.write("guido::0:0::/:/bin/sh
")
我喜欢,但感觉有点太黑魔法了。对读者来说并不完全清楚
@为什么你不定义它,避免每次你需要的时候都这样做?它是在应用程序级别定义的,和任何其他ContextManager一样神奇。我认为使用WITH语句的人会很清楚地理解它(如果您不喜欢它,函数的名称也可能更具表现力)。"with"语句本身就是这样设计的:定义一个"安全"的代码块,并将检查功能委托给上下文管理器(以使代码更清晰)。
所有这些麻烦只是因为没有在用户代码中写入finally块。我开始认为我们都在忍受一个长期的炒作症状。
在Python中处理异常的最佳方法是编写一个函数来捕获并返回异常?真的吗?处理异常的方法是使用try...except语句。
Catching an exception while using a Python 'with' statement
自Python2.6以来,WITH语句在没有__future__导入的情况下可用。您可以早于python 2.5就获得它(但现在是升级的时候了!)用:
from __future__ import with_statement
这是你最需要改正的地方。你快到了,但是with没有except条款:
with open("a.txt") as f:
print(f.readlines())
except: #
print('oops')
一个上下文管理器的__exit__方法,如果它返回False将在错误结束时重报错误。如果它返回True,它将抑制它。open内置的__exit__不返回True,因此您只需要将其嵌套在一个尝试中,除了块:
try:
with open("a.txt") as f:
print(f.readlines())
except Exception as error:
print('oops')
标准样板:不要使用裸露的except:,它可以捕获BaseException和其他可能的异常和警告。至少和Exception一样具体,对于这个错误,可能会捕获IOError。只捕获准备处理的错误。
所以在这种情况下,你应该这样做:
>>> try:
... with open("a.txt") as f:
... print(f.readlines())
... except IOError as error:
... print('oops')
...
oops
采用标准异常处理
try:
with open("a.txt") as f:
#business as usual
except Exception as e:
print"oops, handle exception:", e
然后有一天,文件将在os.path.exists检查和打开之间被删除。
很好,现在修好了:)
不,这不是固定的。如果文件在检查和打开调用之间被删除,它仍然可能失败。
@贾斯珀,你开玩笑吧。你能解释更多吗?
别开玩笑了。这个脚本很可能在多线程环境中运行。这意味着它可以在任何时候被中断,其他线程/进程可以做它们的事情。理论上,有可能1)文件存在于检查过程中2)另一个进程中断并碰巧删除了文件3)脚本继续,但没有文件。
在这种情况下,我们需要在打开、更新之前检查它是否存在。