112

The classical way to program is with try ... catch. When is it appropriate to use try without catch?

In Python the following appears legal and can make sense:

try:
  #do work
finally:
  #do something unconditional

However, the code didn't catch anything. Similarly one could think in Java it would be as follows:

try {
    //for example try to get a database connection
}
finally {
  //closeConnection(connection)
}

It looks good and suddenly I don't have to worry about exception types, etc. If this is good practice, when is it good practice? Alternatively, what are the reasons why this is not good practice or not legal? (I didn't compile the source. I'm asking about it as it could be a syntax error for Java. I checked that the Python surely compiles.)

A related problem I've run into is this: I continue writing the function/method, at the end of which it must return something. However, it may be in a place which should not be reached and must be a return point. So, even if I handle the exceptions above, I'm still returning NULL or an empty string at some point in the code which should not be reached, often the end of the method/function. I've always managed to restructure the code so that it doesn't have to return NULL, since that absolutely appears to look like less than good practice.

12
  • 4
    In Java, why not put the return statement at the end of the try block? Jan 23, 2012 at 18:52
  • 3
    I am sad that try..finally and try..catch both use the try keyword, apart from both starting with try they're 2 totally different constructs.
    – Pieter B
    Sep 18, 2012 at 9:34
  • 3
    try/catch is not "the classical way to program." It's the classical C++ way to program, because C++ lacks a proper try/finally construct, which means you have to implement guaranteed reversible state changes using ugly hacks involving RAII. But decent OO languages don't have that problem, because they provide try/finally. It's used for a very different purpose than try/catch. Apr 25, 2013 at 1:21
  • 3
    I see it a lot with external connection resources. You want the exception but need to make sure that you don't leave an open connection etc. If you caught it you would just rethrow it to the next layer anyway in some cases.
    – Rig
    Dec 19, 2013 at 12:35
  • 4
    @MasonWheeler "Ugly hacks" please, do explain what is bad about having an object handle it's own cleanup?
    – Baldrickk
    Jan 27, 2015 at 11:45

9 Answers 9

178
+300

It depends on whether you can deal with the exceptions that can be raised at this point or not.

If you can handle the exceptions locally you should, and it is better to handle the error as close to where it is raised as possible.

If you can't handle them locally then just having a try / finally block is perfectly reasonable - assuming there's some code you need to execute regardless of whether the method succeeded or not. For example (from Neil's comment), opening a stream and then passing that stream to an inner method to be loaded is an excellent example of when you'd need try { } finally { }, using the finally clause to ensure that the stream is closed regardless of the success or failure of the read.

However, you will still need an exception handler somewhere in your code - unless you want your application to crash completely of course. It depends on the architecture of your application exactly where that handler is.

5
  • 10
    "and it is better to handle the error as close to where it is raised as possible." eh, it depends. If you can recover and still complete the mission (so to speak), yes of course. If you cannot, better to let the exception go all the way to the top, where (likely) user intervention will be required to deal with what happened.
    – Ripped Off
    May 2, 2012 at 12:59
  • 17
    @will - that's why I used the phrase "as possible".
    – ChrisF
    May 2, 2012 at 13:00
  • 10
    Good answer, but I would add an example: Opening a stream and passing that stream to an inner method to be loaded is an excellent example of when you'd need try { } finally { }, taking advantage of finally clause to ensure stream is ultimately closed regardless of success/failure.
    – Neil
    Oct 24, 2012 at 9:35
  • because sometimes all the way on top is as close as one can do
    – Newtopian
    Jan 27, 2015 at 16:46
  • 1
    "just having a try / finally block is perfectly reasonable " was looking exactly for this answer. thank you @ChrisF
    – neal aise
    Jun 24, 2015 at 12:07
40

The finally block is used for code that must always run, whether an error condition (exception) occurred or not.

The code in the finally block is run after the try block completes and, if a caught exception occurred, after the corresponding catch block completes. It is always run, even if an uncaught exception occurred in the try or catch block.

The finally block is typically used for closing files, network connections, etc. that were opened in the try block. The reason is that the file or network connection must be closed, whether the operation using that file or network connection succeeded or whether it failed.

Care should be taken in the finally block to ensure that it does not itself throw an exception. For example, be doubly sure to check all variables for null, etc.

6
  • 9
    +1: It's idiomatic for "must be cleaned up". Most uses of try-finally can be replaced with a with statement.
    – S.Lott
    Jan 23, 2012 at 18:07
  • 13
    Various languages have extremely useful language-specific enhancements to the try/finally construct. C# has using, Python has with, etc.
    – yfeldblum
    Jan 23, 2012 at 18:16
  • 5
    @yfeldblum - there is a subtle diff between using and try-finally, as the Dispose method won't be called by the using block if an exception happens in the IDisposable object's constructor. try-finally allows you to execute code even if the object's constructor throws an exception. Feb 15, 2012 at 16:27
  • 5
    @ScottWhitlock: That's a good thing? What are you trying to do, call a method on an unconstructed object? That's a billion kinds of bad.
    – DeadMG
    Feb 15, 2012 at 16:55
  • 1
    @DeadMG: See also stackoverflow.com/q/14830534/18192
    – Brian
    Apr 25, 2013 at 3:21
17

An example where try... finally without a catch clause is appropriate (and even more, idiomatic) in Java is usage of Lock in concurrent utilities locks package.

  • Here's how it is explained and justified in API documentation (bold font in quote is mine):

    ...The absence of block-structured locking removes the automatic release of locks that occurs with synchronized methods and statements. In most cases, the following idiom should be used:

     Lock l = ...;
     l.lock();
     try {
         // access the resource protected by this lock
     } finally {
         l.unlock();
     }
    

    When locking and unlocking occur in different scopes, care must be taken to ensure that all code that is executed while the lock is held is protected by try-finally or try-catch to ensure that the lock is released when necessary.

3
  • Can I put l.lock() inside try? try{ l.lock(); }finally{l.unlock();}
    – RMachnik
    Jun 25, 2015 at 18:55
  • 1
    technically, you can. I didn't put it there because semantically, it makes less sense. try in this snippet is intended to wrap resource access, why polluting it with something unrelated to that
    – gnat
    Jun 25, 2015 at 18:58
  • 4
    You can, but if l.lock() fails, the finally block will still run if l.lock() is inside the try block. If you do it like gnat suggests, the finally block will only run when we know that the lock was acquired.
    – Wtrmute
    Mar 4, 2016 at 16:32
13

At a basic level catch and finally solve two related but different problems:

  • catch is used to handle a problem that was reported by code you called
  • finally is used to clean up data/resources that the current code created/modified, no matter if a problem occurred or not

So both are related somehow to problems (exceptions), but that's pretty much all they have in common.

An important difference is that the finally block must be in the same method where the resources got created (to avoid resource leaks) and can't be put on a different level in the call stack.

The catch however is a different matter: the correct place for it depends on where you can actually handle the exception. There's no use in catching an exception at a place where you can do nothing about it, therefore it's sometimes better to simply let it fall through.

1
  • 2
    Nitpick: "... the finally block must be in the same method where the resources got created ... ". It is certainly a good idea to do it that way, because it is easier to see there is no resource leak. However, it is not a necessary precondition; i.e. you don't have to do it that way. You can release the resource in the finally of a (statically or dynamically) enclosing try statement ... and still be 100% leak-proof.
    – Stephen C
    Apr 25, 2013 at 4:32
9

In many languages a finally statement also runs after the return statement. This means you can do something like:

try {
  // Do processing
  return result;
} finally {
  // Release resources
}

Which releases the resources regardless of how the method was ended with an exception or a regular return statement.

Whether this is good or bad is up for debate, but try {} finally {} is not always limited to exception handling.

5

@yfeldblum has the correct answer: try-finally without a catch statement should usually be replaced with an appropriate language construct.

In C++, it's using RAII and constructors/destructors; in Python it's a with statement; and in C#, it's a using statement.

These are nearly always more elegant because the initialization and finalization code are in one place (the abstracted object) rather than in two places.

4
  • 2
    And in Java it's ARM blocks
    – MarkJ
    Feb 15, 2012 at 15:33
  • 2
    Supposing you have a badly designed object (For instance, one which doesn't appropriately implement IDisposable in C#) that isn't always a viable option.
    – mootinator
    Feb 15, 2012 at 19:00
  • 1
    @mootinator: can't you inherit from the badly designed object and fix it?
    – Neil G
    Feb 15, 2012 at 22:40
  • 2
    Or encapsulation? Bah. I mean yes, of course.
    – mootinator
    Feb 16, 2012 at 15:26
4

I might invoke the wrath of Pythonistas (don't know as I don't use Python much) or programmers from other languages with this answer, but in my opinion most functions should not have a catch block, ideally speaking. To show why, let me contrast this to manual error code propagation of the kind I had to do when working with Turbo C in the late 80s and early 90s.

So let's say we have a function to load an image or something like that in response to a user selecting an image file to load, and this is written in C and assembly:

enter image description here

I omitted some low-level functions but we can see that I've identified different categories of functions, color-coded, based on what responsibilities they have with respect to error-handling.

Point of Failure and Recovery

Now it was never hard to write the categories of functions I call the "possible point of failures" (the ones that throw, i.e.) and the "error recovery and report" functions (the ones that catch, i.e.).

Those functions were always trivial to write correctly before exception handling was available since a function that can run into an external failure, like failing to allocate memory, can just return a NULL or 0 or -1 or set a global error code or something to this effect. And error recovery/reporting was always easy since once you worked your way down the call stack to a point where it made sense to recover and report failures, you just take the error code and/or message and report it to the user. And naturally a function at the leaf of this hierarchy which can never, ever fail no matter how it's changed in the future (Convert Pixel) is dead simple to write correctly (at least with respect to error handling).

Error Propagation

However, the tedious functions prone to human error were the error propagators, the ones that didn't directly run into failure but called functions that could fail somewhere deeper in the hierarchy. At that point, Allocate Scanline might have to handle a failure from malloc and then return an error down to Convert Scanlines, then Convert Scanlines would have to check for that error and pass it down to Decompress Image, then Decompress Image->Parse Image, and Parse Image->Load Image, and Load Image to the user-end command where the error is finally reported.

This is where a lot of humans make mistakes since it only takes one error propagator to fail to check for and pass down the error for the entire hierarchy of functions to come toppling down when it comes to properly handling the error.

Further, if error codes are returned by functions, we pretty much lose the ability in, say, 90% of our codebase, to return values of interest on success since so many functions would have to reserve their return value for returning an error code on failure.

Reducing Human Error: Global Error Codes

So how can we reduce the possibility of human error? Here I might even invoke the wrath of some C programmers, but an immediate improvement in my opinion is to use global error codes, like OpenGL with glGetError. This at least frees the functions to return meaningful values of interest on success. There are ways to make this thread-safe and efficient where the error code is localized to a thread.

There are also some cases where a function might run into an error but it's relatively harmless for it to keep going a little bit longer before it returns prematurely as a result of discovering a previous error. This allows for such a thing to happen without having to check for errors against 90% of function calls made in every single function, so it can still allow proper error handling without being so meticulous.

Reducing Human Error: Exception-Handling

However, the above solution still requires so many functions to deal with the control flow aspect of manual error propagation, even if it might have reduced the number of lines of manual if error happened, return error type of code. It wouldn't eliminate it completely since there would still often need to be at least one place checking for an error and returning for almost every single error propagation function. So this is when exception-handling comes into the picture to save the day (sorta).

But the value of exception-handling here is to free the need for dealing with the control flow aspect of manual error propagation. That means its value is tied to the ability to avoid having to write a boatload of catch blocks throughout your codebase. In the above diagram, the only place that should have to have a catch block is the Load Image User Command where the error is reported. Nothing else should ideally have to catch anything because otherwise it's starting to get as tedious and as error-prone as error code handling.

So if you ask me, if you have a codebase that really benefits from exception-handling in an elegant way, it should have the minimum number of catch blocks (by minimum I don't mean zero, but more like one for every unique high-end user operation that could fail, and possibly even fewer if all high-end user operations are invoked through a central command system).

Resource Cleanup

However, exception-handling only solves the need to avoid manually dealing with the control flow aspects of error propagation in exceptional paths separate from normal flows of execution. Often a function which serves as an error propagator, even if it does this automatically now with EH, might still acquire some resources it needs to destroy. For example, such a function might open a temporary file it needs to close before returning from the function no matter what, or lock a mutex it needs to unlock no matter what.

For this, I might invoke the wrath of a lot of programmers from all sorts of languages, but I think the C++ approach to this is ideal. The language introduces destructors which get invoked in a deterministic fashion the instant an object goes out of scope. Because of this, C++ code which, say, locks a mutex through a scoped mutex object with a destructor need not manually unlock it, since it will be automatically unlocked once the object goes out of scope no matter what happens (even if an exception is encountered). So there's really no need for well-written C++ code to ever have to deal with local resource cleanup.

In languages that lack destructors, they might need to use a finally block to manually clean up local resources. That said, it still beats having to litter your code with manual error propagation provided you don't have to catch exceptions all over the freaking place.

Reversing External Side Effects

This is the most difficult conceptual problem to solve. If any function, whether it's an error propagator or point of failure causes external side effects, then it needs to roll back or "undo" those side effects to return the system back into a state as though the operation never occurred, instead of a "half-valid" state where the operation halfway succeeded. I know of no languages that make this conceptual problem much easier except languages that simply reduce the need for most functions to cause external side effects in the first place, like functional languages which revolve around immutability and persistent data structures.

Here finally is arguably the among the most elegant solutions out there to the problem in languages revolving around mutability and side effects, because often this type of logic is very specific to a particular function and doesn't map so well to the concept of "resource cleanup". And I recommend using finally liberally in these cases to make sure your function reverses side effects in languages that support it, regardless of whether or not you need a catch block (and again, if you ask me, well-written code should have the minimum number of catch blocks, and all catch blocks should be in places where it makes the most sense as with the diagram above in Load Image User Command).

Dream Language

However, IMO finally is close to ideal for side effect reversal but not quite. We need to introduce one boolean variable to effectively roll back side effects in the case of a premature exit (from a thrown exception or otherwise), like so:

bool finished = false;
try
{
    // Cause external side effects.
    ...

    // Indicate that all the external side effects were
    // made successfully.
    finished = true; 
}
finally
{
    // If the function prematurely exited before finishing
    // causing all of its side effects, whether as a result of
    // an early 'return' statement or an exception, undo the
    // side effects.
    if (!finished)
    {
        // Undo side effects.
        ...
    }
}

If I could ever design a language, my dream way of solving this problem would be like this to automate the above code:

transaction
{
    // Cause external side effects.
    ...
}
rollback
{
    // This block is only executed if the above 'transaction'
    // block didn't reach its end, either as a result of a premature
    // 'return' or an exception.

    // Undo side effects.
    ...
}

... with destructors to automate cleanup of local resources, making it so we only need transaction, rollback, and catch (though I might still want to add finally for, say, working with C resources that don't clean themselves up). However, finally with a boolean variable is the closest thing to making this straightforward that I've found so far lacking my dream language. The second most straightforward solution I've found for this is scope guards in languages like C++ and D, but I always found scope guards a little bit awkward conceptually since it blurs the idea of "resource cleanup" and "side effect reversal". In my opinion those are very distinct ideas to be tackled in a different way.

My little pipe dream of a language would also revolve heavily around immutability and persistent data structures to make it much easier, though not required, to write efficient functions that don't have to deep copy massive data structures in their entirety even though the function causes no side effects.

Conclusion

So anyway, with my ramblings aside, I think your try/finally code for closing the socket is fine and great considering that Python doesn't have the C++ equivalent of destructors, and I personally think you should use that liberally for places that need to reverse side effects and minimize the number of places where you have to catch to places where it makes the most sense.

1
  • 1
    Too bad this user disappered. If most answers held this standard, SO would be better off for it.
    – oligofren
    Nov 21, 2020 at 14:07
0

As several other answers do a good job of explaining, try ... finally ... is indeed good practice in some situations. Here I want to point out that Python language itself gives you a strong hint that it is by giving you the with statement.

As the documentation points out, a with statement is semantically equivalent to a try ... except ... finally ... block. The __exit__() routine that is part of the context manager is always called when the block is completed (it's passed exception information if any exception occurred) and is expected to do cleanup. While it's possible also to handle exceptions at this point, it's quite normal always to let higher levels deal with the exception, and the API makes this easy:

If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.

Neil G suggests that try ... finally ... should always be replaced with a with. I disagree: which you should use depends on whether in that particular situation you feel that readers of your code would be better off seeing the cleanup code right there, or if it's more readable with the cleanup hidden in a an __exit__() method in the context manager object. For frequently-repeated situations where the cleanup is obvious, such as with open('somefile') as f: ..., with works better. For rarer situations where you're doing a more unusual cleanup (say, by deleting a file you failed to write completely) it may be better to have that stated explicitly at the call site.

-69

Catching errors/exception and handling them in a neat manner is highly recommended even if not mandatory.

The reason I say this is because I believe every developer should know and tackle the behavior of his/her application otherwise he hasn't completed his job in a duly manner. There is no situation for which a try-finally block supersedes the try-catch-finally block.

I will give you a simple example: Assume that you have written the code for uploading files on the server without catching exceptions. Now, if for some reason the upload fails, the client will never know what went wrong. But, if you have caught the exception, you can display a neat error message explaining what went wrong and how can the user remedy it.

Golden rule: Always catch exception, because guessing takes time

8
  • 25
    -1: In Java, a finally clause may be needed to release resources (e.g. close a file or release a DB connection). That is independent of the ability to handle an exception. Jan 23, 2012 at 18:47
  • @kevincline, He is not asking whether to use finally or not...All he is asking is whether catching an exception is required or not....He knows what try , catch and finally does.....Finally is the most essential part, we all know that and why it's used.... Jan 23, 2012 at 18:52
  • 67
    @Pankaj: your answer suggests that a catch clause should always be present whenever there is a try. More experienced contributors, including me, believe this is poor advice. Your reasoning is flawed. The method containing the try is not the only possible place the exception can be caught. It is often simplest and best to allow catch and report exceptions from the top-most level, rather than duplicating catch clauses throughout the code. Jan 23, 2012 at 19:25
  • 2
    With exceptions, you want the normal execution of statements to be interrupted (and without manually checking for success at each step). This is especially the case with deeply nested method calls - a method 4 layers inside some library can't just "swallow" an exception; it needs to be thrown back out through all the layers. Of course, each layer could wrap the exception and add additional info; this is often not done for various reasons, additional time to develop and unnecessary verbosity being the two biggest.
    – Daniel B
    Sep 18, 2012 at 11:42
  • 4
    This is actively bad advice. Never catch an exception unless you are prepared to deal with the underlying failure or at least re-throw it. The absolute worst codebase I have ever had to fix contained hundreds of idiotic placebo log-and-quash catch blocks peppered all across it that did nothing for user experience but leave corrupted state for other code to crash on, while actively preventing higher-level code from detecting and recovering from the failures. Crashing immediately is a more correct behavior than blindly quashing exceptions. Mar 5, 2021 at 20:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.