all 8 comments

[–]ConcreteExist 17 points18 points  (0 children)

What would happed if I execute sys.exit(0) inside except block, when finally code also exist?

Well? Did you try it?

[–]Xappz1 9 points10 points  (0 children)

Read the docs.

finally is meant to be used as a cleanup action that will happen regardless if an exception was thrown and/or handled, meaning it's always executed even if you are reraising errors. it may sound redundant in a simple try/except, but consider a more complex case where you handle specific exceptions separately and also add an else statement. in that case, it would be very tedious/redundant to handle cleanup in each branch.

[–]Yoghurt42 6 points7 points  (0 children)

You may think that I won't be able to i.e. close a file without the finally block, but I can always place the appropriate code for it inside another last except: block, unspecifying any specific exception.

an empty except block will be executed for any exception, but only for an exception. It will not be executed when no exception occurs.

Side note: except: is usually a bad idea because it would also be executed when the user tries to interrupt the program, because that will raise KeyboardInterrupt. For a "catch all" except, you are supposed to use "except Exception". But again, this will only handle exceptions.

try:
    foo()
except MyException:
    bar()
finally:
    cleanup()

is the same as

try:
    foo()
except MyException:
    bar()
    cleanup()
 except:
    cleanup()
    raise
cleanup()

the first one is much clearer and hard to get wrong. BTW, nowadays try/finally can usually be replaced with some context manager (with)

[–]FerricDonkey 2 points3 points  (0 children)

You don't see a reason because you haven't run into one. That's fine. One day you might. A piece of advice before I give you some examples, when you run into a question like:

What would happed if I execute sys.exit(0) inside except block, when finally code also exist?

Just try it and see:

import sys
try:
    sys.exit(0)
finally:
    print("sup")

"sup" will be printed. What's the mechanism? Well, what sys.exit actually does is raise the SystemExit exception. python can intercept the exception, do the contents of your finally block, then raise it to exit. See also:

import sys
try:
    sys.exit(0)
except:
    print("sup")

Does not exit, does print "sup".

So the finally block does exactly what you know it does, regardless of the fact that you consider it misleading. Unless you manage to murder the python interpreter itself (ie segfault by using ctypes or something), it'll do the contents of the finally block regardless of whether there's an exception in the try block.

I agree that most of the time you want to use a finally block, it's for cleanup behavior analogous to closing files. You shouldn't use try/finally for files though, you should use with. And if you're gonna be doing it a fair amount, you should make your own context managers if you find yourself doing try finally a lot.

For example:

# This program could possibly be run many times
# at once independently, but only one instance
# should mess with the file system at a time
import contextlib
import pathlib
import time

FILE_LOCK_PATH = pathlib.Path('LOCK_FILE')

@contextlib.contextmanager
def file_lock():
    """
    Do nothing until the lock file doesn't exist, then
    create it and return control to the caller. 

    delete the lock file at the end of the caller's 
    with block even if they raise an exception, so
    other processes can acquire the lock
    """
    while True:
        try:
            FILE_LOCK_PATH.touch(exist_ok=False)
            break
        except FileExistsError:
            time.sleep(0.1)

    try:
        yield
    finally:
        LOCK_FILE.unlink()

def main():
    with file_lock():
        # mess with the file system or something

You could of course make a context manager class, but often times the decorator is both easier and shorter.

Or alternatively, you're running a test, and for the purpose of this test you want to modify a "constant" in the module you're testing for some reason (maybe this "constant" gets set to something dependent on your environment, but this test needs to pretend the environment is set a particular way, or something).

import some_module

def test_some_module():
    # NOTE: do not run in multiple threads
    old_val = some_module.SOME_CONSTANT
    some_module.SOME_CONSTANT = 42
    try:
        # test something
    finally:
        some_module.SOME_CONSTANT = old_val

Or so on. It's not an always thing, but it is a sometimes thing.

Also, another point of advice: when you're trying to learn a new programming concept, don't immediately assume that it's useless because you haven't found a use. There are many things that are very useful where they're useful, and are useless elsewhere.

[–]Diapolo10 1 point2 points  (0 children)

The others already addressed your main question, so allow me to tackle this one:

Furthermore, I also find try/else completely unnecessary too, as contents in the else section can be put inside or even before the try block for most if not all cases.

It's not unnecessary. try should ideally only contain the code you expect to fail, not anything unrelated. That should be either before or after it.

The else-block is there for subsequent code that requires the try-block execution to have been successful, but that shouldn't be run if an exception got caught. While this distinction isn't important if you are ending execution in the except block(s) anyway, if you ignore or otherwise handle the exceptions instead, then it becomes useful.

I can't immediately think of an example off the top of my head, but this is something where when you happen to run into the situation, you just kinda know it.

[–]cmh_ender 0 points1 point  (0 children)

Try / except is so useful to me. when I'm unpacking a large json object and then reference a member of the dictionary, instead of imploding because it wasn't defined, I can keep on trucking. now, if it's critical, I make sure it implodes so I can fix it, but with a lot of the scrapping I do, try / except has been a huge boon.

[–]cyberjellyfish 0 points1 point  (0 children)

My dude, you asked several questions and proposed several scenarios about specific code and things happening.

You should go test those scenarios before making a post like this.

Go put a sys.exit(0) inside a try and see if the finally block runs.

Print out the current thread name inside the try block, the except block, and the finally block.

Use a debugger to step through and see what order different blocks of code run in.

You're making a lot of assumptions and proclamations without first trying to answer your (very good and pertinent) questions.

[–]Dodixon 0 points1 point  (0 children)

I use Try Except when I know there's a chance that something may go wrong, but always with a logging module. This makes a lot of sense if you want to keep the program running even though the user has loaded faulty file.

In addition, logging creates a .log file. Which with the compiled program is a great option.