Using python "with" statement with try-except block
Asked Answered
D

4

123

Is this the right way to use the python "with" statement in combination with a try-except block?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

If it is, then considering the old way of doing things:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

Is the primary benefit of the "with" statement here that we can get rid of three lines of code? It doesn't seem that compelling to me for this use case (though I understand that the "with" statement has other uses).

EDIT: Is the functionality of the above two blocks of code identical?

EDIT2: The first few answers talk generally about the benefits of using "with", but those seem of marginal benefit here. We've all been (or should have been) explicitly calling f.close() for years. I suppose one benefit is that sloppy coders will benefit from using "with".

Dictatorship answered 4/9, 2010 at 11:35 Comment(2)
Possible duplicate of Catching an exception while using a Python 'with' statementBoo
For me, not having to remember to close() things in a finally statement is a good enough reason to use 'with'. I have seen a lot of code failing to close its resources. And 'with' doesn't have drawbacks as far as I can see.Lizzettelizzie
N
158
  1. The two code blocks you gave are not equivalent
  2. The code you described as old way of doing things has a serious bug: in case opening the file fails you will get a second exception in the finally clause because f is not bound.

The equivalent old style code would be:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

As you can see, the with statement can make things less error prone. In newer versions of Python (2.7, 3.1), you can also combine multiple expressions in one with statement. For example:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

Besides that, I personally regard it as bad habit to catch any exception as early as possible. This is not the purpose of exceptions. If the IO function that can fail is part of a more complicated operation, in most cases the IOError should abort the whole operation and so be handled at an outer level. Using with statements, you can get rid of all these try...finally statements at inner levels.

Nonet answered 5/9, 2010 at 1:20 Comment(3)
It's fine to use exceptions early. Python encourages their use for control in many cases.Mahound
Maybe it's a bad habit, but I just always find myself wanting to just "try" specific things, and then be able to know I caught the thing I was trying to catch rather than something else. Mostly so I can write a better error message I guess. So I just find it upsetting to not be able to "try" just the open file here. What if I open some other stuff at the same time? If I just wrap everything in one big try/except IOError then I start to get confused about the causes of any IOErrors. Or the 'except' statement ends up far away from the 'try' in the code and it's purpose becomes unclear.Recommendation
Or say I am opening multiple files at once, and I want to be able to do something if one file exists but not the other? I guess just revert back to explicitly checking in advance which files exist?Recommendation
F
8

If the contents of the finally block are determined by the properties of the file object being opened, why shouldn't the implementer of the file object be the one to write the finally block? That's the benefit of the with statement, much more than saving you three lines of code in this particular instance.

And yes, the way you've combined with and try-except is pretty much the only way to do it, as exceptional errors caused within the open statement itself can't be caught within the with block.

Ferric answered 4/9, 2010 at 11:53 Comment(0)
B
0

I think you got it wrong about "with" statement that it only reduces lines. It actually does initialization and handle teardown.

In your case "with" does

  • open a file,
  • process its contents, and
  • make sure to close it.

Here is link for understanding "with" statement : http://effbot.org/zone/python-with-statement.htm

Edit: Yes your usage of "with" is correct and functionality of both blocks of code is identical. Question about why to use "with" ? it's because of benefits you get with it. like you mentioned about accidentally missing f.close().

Britteny answered 4/9, 2010 at 11:55 Comment(0)
Z
-8

The more Pythonic way for the following codes is:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

try:
    f = open("file", "r")
except IOError:
    <whatever>
else:
    f.close()
Zeniazenith answered 13/10, 2015 at 21:21 Comment(2)
I've added code formatting for you; it makes it easier to read. But you might want to double-check to make sure that I've not broken the indenting.Myrmidon
No, your version does not do the same thing as the original code. Even if you add the missing readline() call, your version does not close the file if the readline() results in an IOError.Psychotomimetic

© 2022 - 2024 — McMap. All rights reserved.