4
zip_file_name = "not_exist.py"

try:
   with zipfile.ZipFile(zip_file_name) as f_handle:
       print("open it successfully")
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
       print(e)

Is this the correct way to handle exception throw by a with statement?

q0987
  • 34,938
  • 69
  • 242
  • 387
  • 3
    possible duplicate of [Catching an exception while using a Python 'with' statement](http://stackoverflow.com/questions/713794/catching-an-exception-while-using-a-python-with-statement) – Cédric Julien Oct 13 '11 at 16:32

2 Answers2

5

Yes, this is how you would want to handle exceptions from inside a with statement. ContextManagers (that implement the behavior behind the with statement) can handle exceptions but should only do so to properly clean up resources used by the object.

Here's a snippet from the relevant documentation:

If BLOCK raises an exception, the context manager’s exit() method is called with three arguments, the exception details (type, value, traceback, the same values returned by sys.exc_info(), which can also be None if no exception occurred). The method’s return value controls whether an exception is re-raised: any false value re-raises the exception, and True will result in suppressing it. You’ll only rarely want to suppress the exception, because if you do the author of the code containing the ‘with‘ statement will never realize anything went wrong.

Chris Phillips
  • 11,607
  • 3
  • 34
  • 45
  • 1
    While that is correct, it's not the full story. That documentation refers to exceptions coming from the BLOCK part of the with statement. It is *not* applicable to exceptions from the expression that returns the ContextManager. If you look at the types of exceptions the OP is catching, it seems that the OP is interested in the latter. – Mark Byers Oct 13 '11 at 16:55
3

Yes, that's fine.

Another alternative is:

try:
   f_handle = zipfile.ZipFile(zip_file_name)
   # no more code here
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
   print(e)
else:
   with f_handle:
      print("open it successfully")

This prevents you from accidentally catching an exception from the body of the with statement in your except handler.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • This won't give the ZipFile a chance to cleanup ( the `__exit__` portion of the ContextManager ) if an exception occurs after resources have been acquired. If you're going to go down this route, I suggest using try/except/finally instead. – Chris Phillips Oct 13 '11 at 16:37
  • @Chris Phillips: Hmm.... What exceptions can occur between the assignment succeeding and the with statement being called? – Mark Byers Oct 13 '11 at 16:43
  • @Mark, I guess that Chris had made assumption that more code can be added following the assignment statement. I have made a comment in your code and see it works for him. – q0987 Oct 13 '11 at 16:47