By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,182 Members | 1,521 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,182 IT Pros & Developers. It's quick & easy.

getting with statement to deal with various exceptions

P: n/a
mk
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.

Jul 20 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a

"mk" <mr****@gmail.comwrote in message
news:ma************************************@python .org...
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.
I just started looking at the with statement myself. How about:

from __future__ import with_statement

class ExceptionManager(object):
def __enter__(self):
pass
def __exit__(self,exc_type,exc_value,tb):
if exc_type == IOError:
print 'IOError',exc_value[1]
return True # suppress it

with ExceptionManager():
with open('test.txt') as f:
f.read()

--
Mark

Jul 20 '08 #2

P: n/a
mk
from __future__ import with_statement

class ExceptionManager(object):
def __enter__(self):
pass
def __exit__(self,exc_type,exc_value,tb):
if exc_type == IOError:
print 'IOError',exc_value[1]
return True # suppress it

with ExceptionManager():
with open('test.txt') as f:
f.read()
Neat. I think I'm going to use this approach, since BDFL-in-chief is
unlikely to listen to me in any foreseeable future. :-)

Jul 20 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.