473,473 Members | 1,963 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Why no try-except-finally ?

This may have been discussed before, but I'm kind of confused as to why Python
doesn't support having both an except ~and~ a finally clause, like this:

try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This doesn't work because I use both 'except' and 'finally'. I'm not saying
that it SHOULD work, I'm wondering why it doesn't. I thought about it for a
second, though, and came up with the ad-hoc "nested-try idiom", as I call it:

try:
try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This works as expected: the exception gets thrown, the question gets asked in
the 'except' clause, and then the question gets answered in the 'finally'
clause. Of course in real-world code we wouldn't be asking questions and giving
answers via exception-handling, but the path of execution is what counts. Is
this idiom unPythonic somehow? (The nested-try thing does look odd...) Or is it
the way we're supposed to do it? Or is there something I'm missing?

- Kef

Jul 18 '05 #1
13 11941
>This may have been discussed before, but I'm kind of confused as to why
Python
doesn't support having both an except ~and~ a finally clause, like this:

try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This doesn't work because I use both 'except' and 'finally'. I'm not saying
that it SHOULD work, I'm wondering why it doesn't. I thought about it for a
second, though, and came up with the ad-hoc "nested-try idiom", as I call it:

try:
try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This works as expected: the exception gets thrown, the question gets asked in
the 'except' clause, and then the question gets answered in the 'finally'
clause. Of course in real-world code we wouldn't be asking questions and
giving
answers via exception-handling, but the path of execution is what counts. Is
this idiom unPythonic somehow? (The nested-try thing does look odd...) Or is
it
the way we're supposed to do it? Or is there something I'm missing?

- Kef
I messed up a couple things in my post, heh. First off, of course
RuntimeException should be RuntimeError. The other is that this (the nested try
idiom):
try:
try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42


should instead be this:

try:
try:
raise RuntimeError
except:
print "What is the answer?"
raise # <- HAD BEEN FORGOTTEN
finally:
print 42

- Kef
Jul 18 '05 #2

"KefX" <ke**********@aol.comNOSPAM> wrote in message
news:20***************************@mb-m22.aol.com...

this idiom unPythonic somehow? (The nested-try thing does look odd...) Or is it the way we're supposed to do it? Or is there something I'm missing?


According to the documentation the purpose of a try...finally statement is
to ensure that aquired ressources will be freed again as in

self.lock.acquire()
try:
..do whatever we are supposed to do;
...it may fail here or in a different module etc.
...exceptions may be caught or not
finally:
...but we always end *here*
...and uncaught exceptions are re-raised from here too (i think)
...so that "the right thing" happens
self.lock.release()

so that the ressource is released regardless of any exceptions etc. that
happens between the try: and the finally:

The separation is probably because the purpose of try..finally is different
from exception handling and mixing the two would obscure that (or maybe
there is some wizardry under the hood).
Jul 18 '05 #3
>The separation is probably because the purpose of try..finally is different
from exception handling and mixing the two would obscure that (or maybe
there is some wizardry under the hood).


I dunno. Other languages such as Java support "try-catch-finally" (or
"try-except-finally" as we're calling it), and I don't see how the lack of
restrictions does anything bad like, say, reduce the clarity of code.

I bring this up because I originally wrote this in my game code:

try:
PlayGame()
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
finally:
DeInit()

In other words, if something went wrong, an error message would be printed out
to the log, and then in either case, my game would try to exit gracefully. Of
course, rewriting it without the finally: is no big deal (just write DeInit()
in the except block and again after the block)...in this case. What if I wanted
to execute a bunch of lines? Code duplication is bad. Well, I could write a
local function and just have it call THAT in both cases, but that felt like
overkill. Thus, I came up with the 'nested-try idiom':

try:
try:
PlayGame()
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
raise
finally:
DeInit()

But it looks kind of ugly. But it's still easy to just change the statements in
the 'finally' block if needed. But the nested-try looks strange, and worse, you
have to remember to put the 'raise' in the except block (remember I forgot to
do this in my original post!), and error-handling code tends to be the
least-tested...

I dunno. More thoughts?

- Kef

Jul 18 '05 #4
KefX wrote:
I dunno. Other languages such as Java support "try-catch-finally" (or
"try-except-finally" as we're calling it), and I don't see how the
lack of
restrictions does anything bad like, say, reduce the clarity of code.


The claim is that some user polling indicated that newbies didn't really
understand how the try...except...finally syntax was supposed to work,
and thus it was eliminated for the sake of clarity. I'm not sure I buy
the argument, but that's why.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \ Granted that I must die, how shall I live?
\__/ Michael Novak
Jul 18 '05 #5
ke**********@aol.comNOSPAM (KefX) wrote in
news:20***************************@mb-m22.aol.com:
I bring this up because I originally wrote this in my game code:

try:
PlayGame()
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
finally:
DeInit()

In other words, if something went wrong, an error message would be
printed out to the log, and then in either case, my game would try to
exit gracefully. Of course, rewriting it without the finally: is no
big deal (just write DeInit() in the except block and again after the
block)...in this case. What if I wanted to execute a bunch of lines?
Code duplication is bad.


Hang on, there is something wrong with what you say here. If you really had
the code you wrote above, and you put DeInit() in the except block and
again after it then any time an exception was thrown you would call DeInit
twice. Is this *really* what you wanted?

This code would reliably call DeInit every time, whether or not an
exception was thrown, without code duplication:

try:
PlayGame()
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
DeInit()

--
Duncan Booth du****@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
Jul 18 '05 #6
ke**********@aol.comNOSPAM (KefX) wrote in
news:20***************************@mb-m22.aol.com:
This may have been discussed before, but I'm kind of confused as to
why Python doesn't support having both an except ~and~ a finally
clause, like this:

try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This doesn't work because I use both 'except' and 'finally'. I'm not
saying that it SHOULD work, I'm wondering why it doesn't.


The first thing to ask yourself when wondering why something doesn't work
in Python, is exactly what you expect it should do.

The 'try' block can exit normally; by throwing an exception that is caught
by an 'except'; or by throwing an exception that is not caught and
propogates outside. Do you want the 'finally' block executed in all of
those cases, or only for some of them?
The answer to your question, given by Tim Peters in
http://groups.google.com/groups?selm...GIAA.tim_one%4
0email.msn.com
is that Python used to allow this, and people got caught out because it
didn't work the way everyone expected. By writing try/except/else and
try/finally separately you can clearly communicate what you expect to
happen.

--
Duncan Booth du****@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
Jul 18 '05 #7
>Hang on, there is something wrong with what you say here. If you really had
the code you wrote above, and you put DeInit() in the except block and
again after it then any time an exception was thrown you would call DeInit
twice. Is this *really* what you wanted?


Err, no, it'd also exit with an error code in the except block (something I
hadn't written in at that moment because I had already realized it wasn't going
to work that way). My bad.

For now I rewrote it like this, just a modified version of what you suggested:

err_code = 0
try:
game.Play() # was PlayGame() before
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
err_code = 1

DeInit()
return err_code
Jul 18 '05 #8
KefX wrote:

For now I rewrote it like this, just a modified version of what you suggested:

err_code = 0
try:
game.Play() # was PlayGame() before
except:
err_msg = "FATAL ERROR: " + sys.exc_info()[0]
logger.critical(err_msg)
err_code = 1

DeInit()
return err_code


Somewhat better style, generally, IMHO, would be to replace "err_code = 1"
with "raise" in the above. Consider returning error codes to be a
parallel (and somewhat obsolescent) way of communicating failures to
calling code. Raising an exception should be generally preferred.

Note, however, that doing this (re-raising the exception) brings
you back to your original query as well, as DeInit() would not get
called if it were not in a try/finally.

A second style point: use a general try/except (without specifying
the exceptions to be caught) is usually a Very Bad Idea. It's okay
at the top level of a module, but it will mask all kinds of bugs
at the lower levels. For example, in the above you might have
misspelled Play() as play() and you would get an AttributeError,
but would think that it was the call to Play() which had raised
an exception and the "FATAL ERROR".

Again, however, restricting the set of exceptions called means that
in the case where one of the unhandled ones is raised (unhandled at
this particular level, anyway), you still want a finally clause
to ensure DeInit() is executed.

I'd say, in response to the original question, that the nested
try/except in the try/finally is the appropriate, preferred Pythonic
idiom.

-Peter
Jul 18 '05 #9
JCM
KefX <ke**********@aol.comnospam> wrote:
This may have been discussed before, but I'm kind of confused as to why Python
doesn't support having both an except ~and~ a finally clause,


I miss this as well.
Jul 18 '05 #10
I look at it this way. You are either handling exceptions or you are
letting them propagate up the stack. If you handle them, then there
is no need for the finally as you will remain in the function and you
can release resources at the bottom of the try/except block.

try: pass
except: pass
#release resources here

If you are letting all exceptions propagate up the stack then there is
no except clause
try: pass
finally: #release resources

Of course there may be cases where some exceptions are handled and
others are not. Or an exception is partially handled, and then
rethrown. In these cases, it seems a try/catch/finally idiom would be
useful.

I believe that Delphi works the same way as Python in this regard.
Jul 18 '05 #11
>Somewhat better style, generally, IMHO, would be to replace "err_code = 1"
with "raise" in the above. Consider returning error codes to be a
parallel (and somewhat obsolescent) way of communicating failures to
calling code. Raising an exception should be generally preferred.


I agree with you in general, but this code is in my main() function, and
returning an error code one way or another is the only way to report the error
status to the OS. :)

Instead of this:

if __name__ == '__main__':
main()

my code does this:

if __name == '__main__':
sys.exit(main())

I believe Guido suggested that idiom in his blog.

- Kef

Jul 18 '05 #12
KefX wrote:
Somewhat better style, generally, IMHO, would be to replace "err_code = 1"
with "raise" in the above. Consider returning error codes to be a
parallel (and somewhat obsolescent) way of communicating failures to
calling code. Raising an exception should be generally preferred.


I agree with you in general, but this code is in my main() function, and
returning an error code one way or another is the only way to report the error
status to the OS. :)

Instead of this:

if __name__ == '__main__':
main()

my code does this:

if __name == '__main__':
sys.exit(main())

I believe Guido suggested that idiom in his blog.


Ah, then I would suggest moving the code that requires proper cleanup
(the finally part) down a level, and simplify the top level so that
all it does is catch all exceptions and convert to an error value
which it then returns.

Works out to about the same thing as saying "nest the try clauses"
but at least it has the advantage of higher cohesion in the two
separate code areas.

-Peter
Jul 18 '05 #13
Shame, shame...it doesn't look like you Google'd enough
http://www.google.com/groups?hl=en&l....nl%26rnum%3D2

Dan ;-)

On 05 Nov 2003 09:05:56 GMT, ke**********@aol.comNOSPAM (KefX) wrote:
This may have been discussed before, but I'm kind of confused as to why Python
doesn't support having both an except ~and~ a finally clause, like this:

try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This doesn't work because I use both 'except' and 'finally'. I'm not saying
that it SHOULD work, I'm wondering why it doesn't. I thought about it for a
second, though, and came up with the ad-hoc "nested-try idiom", as I call it:

try:
try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42

This works as expected: the exception gets thrown, the question gets asked in
the 'except' clause, and then the question gets answered in the 'finally'
clause. Of course in real-world code we wouldn't be asking questions and giving
answers via exception-handling, but the path of execution is what counts. Is
this idiom unPythonic somehow? (The nested-try thing does look odd...) Or is it
the way we're supposed to do it? Or is there something I'm missing?

- Kef


Jul 18 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
by: White Wolf | last post by:
Hi, I cannot believe my eyes, but so far I could not find out what is the name of the construct, which is built from one try block and the catch clauses (handlers). I am not looking for a...
3
by: valued customer | last post by:
Is there a more concise way to do something like the the desired code below? The gripe is with the try-catch syntax. It takes *way* too many lines of code to evaluate a conditional expression...
11
by: kaeli | last post by:
Hey all, I'd like to start using the try/catch construct in some scripts. Older browsers don't support this. What's the best way to test for support for this construct so it doesn't kill...
10
by: Bungle | last post by:
Hi I am trying to do something really simple. Create a method within a class which will connect to the database, pull back a result and return it out the method. Not hard. All my database...
9
by: Mark | last post by:
Hello I'm trying to use a Server.Transfer in a try-catch (I cannot put it outside the Try-Catch as it is nested deep within a component that is called in a try-catch loop) The problem is that the...
4
by: bienwell | last post by:
Hi all, I'd like to use TRY, CATCH to open my database connection. I have 2 servers that have the same table name "myTable". If the first connection to Server1 is failed, then the program will...
9
by: Ed Staffin | last post by:
Hi, In vb6, if I had an error handler I could catch an error, make a correction and then try it again using resume. I want to do the same thing in vb.net. I am trying to deal with some...
4
by: ksukhonosenko | last post by:
This message was originally posted to comp.lang.c++.moderated ---------------------------------------------------------------------------------------------- Hi! I face a problem in my...
3
by: =?Utf-8?B?SmVycnk=?= | last post by:
Hi All, I want to fill some textbox with properties from Active Directory. The fact is if the property is unavailable the program will crash. You can prevent this by using a try and catch. So...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.