问题
Is there a way I can catch exceptions in the __enter__
method of a context manager without wrapping the whole with
block inside a try
?
class TstContx(object):
def __enter__(self):
raise Exception("I'd like to catch this exception")
def __exit__(self, e_typ, e_val, trcbak):
pass
with TstContx():
raise Exception("I don't want to catch this exception")
pass
I know that I can catch the exception within __enter__()
itself, but can I access that error from the function that contains the with
statement?
On the surface the question Catching exception in context manager __enter__() seems to be the same thing but that question is actually about making sure that __exit__
gets called, not with treating the __enter__
code differently from the block that the with
statement encloses.
...evidently the motivation should be clearer. The with
statement is setting up some logging for a fully automated process. If the program fails before the logging is set up, then I can't rely on the logging to notify me, so I have to do something special. And I'd rather achieve the effect without having to add more indentation, like this:
try:
with TstContx():
try:
print "Do something"
except Exception:
print "Here's where I would handle exception generated within the body of the with statement"
except Exception:
print "Here's where I'd handle an exception that occurs in __enter__ (and I suppose also __exit__)"
Another downside to using two try
blocks is that the code that handles the exception in __enter__
comes after the code that handles exception in the subsequent body of the with
block.
回答1:
You can catch the exception using try
/except
inside of __enter__
, then save the exception instance as an instance variable of the TstContx
class, allowing you to access it inside of the with
block:
class TstContx(object):
def __enter__(self):
self.exc = None
try:
raise Exception("I'd like to catch this exception")
except Exception as e:
self.exc = e
return self
def __exit__(self, e_typ, e_val, trcbak):
pass
with TstContx() as tst:
if tst.exc:
print("We caught an exception: '%s'" % tst.exc)
raise Exception("I don't want to catch this exception")
Output:
We caught an exception: 'I'd like to catch this exception'.
Traceback (most recent call last):
File "./torn.py", line 20, in <module>
raise Exception("I don't want to catch this exception")
Exception: I don't want to catch this exception
Not sure why you'd want to do this, though....
来源:https://stackoverflow.com/questions/24878601/catching-an-exceptions-in-enter-in-the-calling-code-in-python