On Tue, 08 Jul 2014 01:49:58 +0200, Alex Burke wrote: > Hi there, > > While reading up on a previous thread 'open() and EOFError' I saw the > following (with minor changes to help make my question clearer) block > suggested as a canonical way to open files and do something:
Emphasis on "a" canonical way, out of many canonical ways ;-) > try: > f = open(path) > except IOError: > handle_error() > else: > with f: > do_stuff() I wrote it that way to show that there is no need to fall back on the old- fashioned "try...except...finally" idiom that was used before the with statement and context managers. In practice, I would usually do what you do: > This somewhat surprised me because I'd always written such a block > something more as follows: > > try: > with open(path) as f: > do_stuff() > except IOError: > handle_error('file never opened') > except ApplicationError: > handle_error('doing something with the content went wrong') assuming that open() and do_stuff() don't raise the same exceptions. If they do raise the same exceptions, and it is important to distinguish IOError raised by open() from IOError raised by do_stuff, then you cannot use this idiom. > Aside from the pythonic but less widely known else clause of the > try/except in the first form, what else is different? What nuances am I > missing? > > The reason I preferred the second was in addition to catching the > IOError when attempting the open() if the file does not exist I thought > I was accounting for the possibility en error occurs while reading data > out of the file. That and to handle if do_stuff() was actually calling > readline() or such on the file which I thought was possible source of > issues. Correct. But now imagine you're happily reading through the file, processing line after line, and halfway through the file read() fails because it's on a network share and somebody just tripped over the cable. Your script now *lies to you* and says the file was never opened. If you care about accurate error messages, you should be more careful about conflating two different errors (that is, catching too much in a single try...except block). > I am wondering if this is also related to some misunderstanding around > the file context manager - on exit of the with() block a close is > arranged, but if that close() is called in an error situation I was > under the impression that the error would be raised again outside it. In general, context managers may choose whether or not to re-raise exceptions. Some exceptions are not errors and may be swallowed silently. However, file objects will re-raise the error. Interestingly, did you know that even *closing* a file can fail? -- Steven -- https://mail.python.org/mailman/listinfo/python-list