Hello,

I'm trying to learn how with statement can be used to avoid writing:

prepare()
try:
        something_that_can_raise_SomeException()
except SomeException, err:
        deal_with_SomeException
finally:
        tear_it_down()

Verbose, not very readable. OK, "with" to the rescue?

Let's take a textbook example from PEP:

with open('/etc/passwd', 'r') as f:
    BLOCK

Well, great, it's neat that "with" closes the file after BLOCK has finished execution, but what if the file isn't there and attempt to open it raises IOException? I'd like to be able to catch it precisely to avoid writing verbose try: .. except: .. finally: .. blocks which as I understand has been much of the rationale behind creating "with" statement in the first place.

"with" statement only allows easy dealing with prepare() and tear_it_down(). When I try to get it to deal with exceptions that might happen, it becomes more complicated:

class FileContextManager:
        def __enter__(self, filename, mode):
                f = open(filename, mode)
                return f
        def __exit__(self, etype, evalue, etraceback):
                print "etype", etype, "evalue", evalue, "etraceback", etraceback

                
>>> with FileContextManager("somefile", "r") as f:
        a = f.readlines()

        

Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    with FileContextManager("somefile", "r") as f:
TypeError: this constructor takes no arguments


Bummer.

Plus, no documentation I've read (on effbot, in PEP 343, etc) says how to deal with the exception happening in __enter__ method of context manager, which is precisely what I'd like to do.

This is only natural, isn't it? When e.g. reading the file, preparation phase is typically checking if it can be opened in the first place. So it falls into __enter__ method of context manager.

"with" limited only to successful execution of a_statement from "with a_statement" seems like limited benefit to me.

I'd like to be able to write smth like

class FileContextManager:
        def __enter__(self, filename, mode):
                f = open(filename, mode)
                return f
        def __except__(IOError, err):
                do_this
                print err
        def __except__(RuntimeError, err):
                do_that
                print "something bad happened", err
        def __exit__(self, etype, evalue, etraceback):
                print "etype", etype, "evalue", evalue, "etraceback", etraceback

__exit__ deals with exceptions happening in the BLOCK below "with" statement, not with exceptions raised in "a_statement", when executing

with a_statement as var:
        BLOCK

In the above way "with" would give me the benefit of more terse, but still understandable and efficient code.

Well, I can always do this:

try:
        with open("somefile.txt") as txtfile:
                for line in txtfile:
                        print line
except IOError:
        print "No such file."

        
No such file.


But that's just ugly, nested too many times (flat is better than nested, right?) and not all that more readable.



--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to