M
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
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'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
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.