Is "finally" Useless In Python?
HTML-код
- Опубликовано: 1 июн 2024
- Today, we're going to be diving into the "finally" keyword. You don't want to know how many comments I get regarding the inutility of "finally" in Python. Sometimes I want to go hide in the forest when I read those comments, but I'm an adult who pays taxes, so instead I'm here to explain what it does!
▶ Become job-ready with Python:
www.indently.io
▶ Follow me on Instagram:
/ indentlyreels
00:00 Learning Python made simple
00:05 “finally is useless
00:27 an example using “finally”
01:58 “finally” is stronger than exceptions
03:13 “finally” is too powerful
03:51 “finally” can be abused
05:01 PEP 601
05:37 “finally” black magic
06:41 What do you think?
I learned about using finally for releasing locks in concurrent programming. My professor said that if you don’t release the lock in a finally, what can happen is like going into the bathroom, locking the door, and then jumping out the window.
Defensive programming for the win!
I like your professor, that's an example I can clearly relate to.
It is good that in Russia no windows in bathrooms
@@cherimolah9493 only linux in russian bathrooms
Very useful for closing out db connections and for "clients" to send hearbeat "lost connection" status
Yeah finally is great for manually closing DB connections. Could you also use a context manager though, to handle that?
Actually, does anyone know how a developer would use the try/except/finally block with a context manager (i.e. the "with" keyword)?
@@RedShipsofSpainAgain Definitely, `with` is much nicer...
@@xbylina2641 I’m not sure, but I remember seeing a video that said the With context manager is actually implemented by using try/ finally
@@RedShipsofSpainAgain doesn't the context lib context manager decorator just wrap your function in try/except/finally?
with statement: am i a joke to you?
FYI. In python, only os._exit() will terminate the python process directly. Since it execute the system call. Other kind of exit() methods will raise a SystemExit and let you catch that.
what if you do os.system('taskkill /f /im python.exe')
@@Bl0xxy not sure about Windows, but on Linux it also exits directly:
~$ python
Python 3.11.8 (cpython) on Linux
>>> import os
>>> try:
... os.system('killall python')
... finally:
... print('Bye!')
...
Terminated
~$
@@Bl0xxydoesn't work on Linux
@@schwingedeshaehers linux distros have their own forms of task kill (idk what they are called tho)
@@Bl0xxy its kill with the task number for normal shutdown
, killall for the name
and with -9 to force
also, i think yours end all python scripts on that user
Finally, concept understood perfectly. Thanks.
Probably best example of why finally is useful is for avoiding file handle leaks. If you're not using a context manager to open a file, it's always important to close the file. So putting it in a finally is a good idea to assure it's closed even in the case of an exception or program exit.
But wouldn't the interpreter when exiting destroy all objects automatically? (I know the importance of freeing objects, I am just curious)
It shouldn't come as a surprise that `sys.exit()` still executes the `finally` block as it works by raising the SystemExit exception so you can catch and handle the exit just like any other exception.
Database connections and files are usually better handled with context managers rather than using finally but just occasionally that isn't appropriate and even when context managers do work they probably use finally in their implementation.
In python, only os._exit() will terminate the python process directly. Since it execute the system call. Other kind of exit() methods will raise a SystemExit and let you catch that.
3:34 the reason it is out of order is because pycharm automatically puts the CLI argument "pythonbuffered=0" or something like that, it essentially makes it so that nothing that gets printed in the console is buffed before being shown on screen with the purpose of catching bad stuff happening much faster that otherwise wouldn't be caught
the side effect of this is that console statements can actually be outside of order when an exception happens or it closes down. I'm not fully sure but I think if you specifically turn that setting off, it should always be in order, or at least more consistently.
They are printed in the correct order. The video is just mistaken about how sys.exit() behaves. That function raises a SystemExit exception, it does not exit immediately. The exception passes through the finally block which executes first as it normally does for all exceptions. Then the python interpreter catches the unhandled SystemExit exception and prints its message “Terminating program” and then exits.
Without the "finally" keyword, my current running US project got experienced burnout. I heavily relied on the "finally" keyword throughout my codebase, especially for tasks such as opening and closing drivers, among other operations.
Finally should be renamed "no matter what".
Good way to think of it. I didn't know it could overcome a return or sys.exit()
...or "always:"
I think the best possible name is "ensure"
or "finally"
Honestly it makes perfect sense if you consider the origins of it in lisp/c++/java, the keywords try/catch/finally actually make sense semantically
First you try to do something, then you catch any errors that pop up, and then finally you do something else no matter what happened
If you want to change the keywords for clarity, might as well go full ansible and just rename them to block/rescue/always since thats what they are: a block of code, some rescue code coming back from errors, and some code that always runs
if you feel that the keyword `finally` is something useless, i think you haven't found the right conditions to apply the keyword.
finally someone said it
Lmao pun intended?
There are soooo many resources for Python beginners, but channel as yours is one of a gems for semi-advanced+ Very well put together, clearly explained... what to want more? Thank you for this and all other videos, subbed for life! :D
When this is called "semi-advanced" I have 0 hope in the future of programmers.
@@noobgam6331 These are concepts that don't appear in beginner videos, it's like a few steps after beginner. "semi-advanced" isn't so bad
@@xsamueljr while this is certainly not beginner level, it's not far enough from it to be considered advanced in any manner.
People who did not know this, are either too used to libraries doing it for them, or have not been involved in opening closing stuff programmatically all that much.
Amateur mistake, finally is a keyword of the gods, there have been so many times where an unknown bug hits in production and this finally block saved me by sending a last call for help like saving a file that was painstakingly calculated or a metric log to splunk. Honestly, I would think that learning how to use finally is an aspect of a professional python programmer, in the same ranks as knowing how to write and use decorators
It's not only fundamental to Python, it's fundamental to most core programming. Someone writing professional code without knowing how to properly use "finally" is troubling...
@@joshman1019 Having this problem (exception handling) being just invented by the IBM right out of their asses and shoved to the world to the point it is now common knowledge is truly troubling tho. I would like to hope that people will migrate to errors as values and slowly forget the try-catch construct alltogether.
@@gamerzero6085 Exceptions in most languages are stored in an exception object, so fundamentally they are a value. (we can also return a full stack-trace). The try/catch/finally block can handle cases where external resources/file locks have been allocated but not yet released. The finally clause will fire whether there was an exception or not. So we then have an in-context area to de-allocate those resources/file locks while we still have access to the variable containing the reference pointer. If we simply return the exception as a value, the exception can only be received by the caller, thus losing the context in which the external resource was allocated. Therefore, you would have a memory leak.
This is something that has to be addressed in languages with a garbage collector, and is just good practice anyway.
The really underused part of the try/except syntax in Python is the else. That's the perfect place to put the continue towards the end of the video.
It's underused because it's not recommended due to readability issues. I personally wouldn't use it unless it was a last resort, and still I would have to leave comments so future devs won't die reading my code.
@@Indently Completely agree with this.
You should have a happy path and the exceptions that deviate from this. The 'else' should just be the rest of your code.
It feels like a way to eliminate nesting, when nesting is precisely what you should be doing OR adjusting your approach to make nesting unnecessary.
Excellent! ❤️
It's amazing, keep it up. 💯
Another awesome use of “finally” is to create a context manager function. It’s way quicker than creating a context manager class with __enter__ and __exit__ methods.
Indeed. While the rise of context managers have decreased the usefulness of finally to some degree, sometimes a context manager is sledgehammer when all you need is a rubber mallet.
You are just made for doing more pythonic operations, Big respect 💪🏻
Finally is exceptionally useful when working with databases as well, as it allows you to ensure rollbacks happen if any errors occur during transactions.
The way I think about it is you put code in finally that you want to run regardless, for example whether a database query succeeds or fails you may want to close the connection
very useful in pytest if you want to let the assert exception get captured but still want to do some finally closing/cleanup logic for a specific test
Using Try except finally are very bad idea inside Test Cases.
You should separate your test cases to checkout extra logics.
Shouldn't you use pytest fixtures to handle all the cleanup?
@@xsamueljr if you need to do something for a specific test rather than something reusable it can be a bit cleaner and clearer
This is why exceptions are the worst. If only we had errors as values
closing db connections or driver.close() in selenium is basically when I use it
isn't that what the "with" keyword is for?
@@timseguine2 you can use that, sure but I don't always. It kind of depends on the program scope for me, especially if I use concurrent futures.
@@FrocketGaming I come from C++, so I usually think in terms of RAII, and "with" scoping fits with that more naturally.
@@timseguine2 I think you bring up a good point, something to think about next time I need this implementation.
Yeah i was like but what if exception thrown in try is not handled by except
That's also a good scenario!
Syntax Error.
@@DhavalAhir10No ?
Does it loop continuously if you swap the continue on the finally for a break in that while true example?
Similarly if an exception isn’t raised will finally have any effect on the loop?
Another great video!! Thumbs 👍
Someone asked a similar question in the comment section of mCoding's video. In my reply I did find `finally` was "technically" useless. It only saves a few lines of code compared to making multiple `except` blocks for the same functionality. However, try/except/finally is much more readable than the code without finally, and saves you from the risk of writing an exception that catches everything. I'll put the same example:
Sometimes we want to ignore the exception, and sometimes we want to perpetuate it. We need a way to keep track of that. I store the error in `error` and check if it is undefined at the end of the try/except block to see if any errors were thrown that we do care about:
```
throw = random.choice(["value","other"])
error = None
fp = open("test.txt", "w")
try:
if throw == "value":
raise ValueError("bad")
else:
raise Exception
except ValueError:
print("There was a value error")
except Exception as err:
print("Something else went wrong")
error = err
fp.close()
if error != None:
raise error
print("Keep working")
```
Finally is useful as shorthand to do the same thing. Finally perpetuates errors raised in exception blocks:
```
fp = open("test.txt", "w")
try:
if throw == "value":
raise ValueError("bad")
if throw == "other":
raise Exception
except ValueError:
print("There was a value error")
finally:
print("Something else might have went wrong")
fp.close()
print("Keep working")
```
As it turns out, this is a case where using `except Exception` is actually useful rather than bad practice, but I can see many beginners messing this part up. Finally does not block/ignore exceptions, it puts them off until it's done working.
"Technically" we don't need `finally`, but it avoids boilerplate, is more readable, and helps the developer avoid making a simple mistake by using `except Exception` wrong.
what ide are you using, it's similar to VSCode but it's not vscode is it?
i think that's pycharm?
@@Captain8771OnGithub woah, since when has pycharm looked so fresh, last time i used it it was looking so bad
I love the arrogance of new programmers who immediately rule anything they don't personally use as "useless"😂
The Dunning-Kruger effect is incredibly strong. It has become my favourite effect to quote.
@Indently Mine too, but it makes me super conscious that I may know less about the effect than I think I do.
there's always that one method that you never seem to think of a use for until you do something that needs it and then feel extremely grateful for its existence
What you did not discuss is what happens if the finally block raises an exception.
I was recently told that it goes up to the previous except block and will run code in there.
What I'm uncertain of is as to what happenes after running the code within the except block in such a circumstance...does it then get stuck in a loop bouncing between the finally and the except block?
🤔
Just tried, it does and raises the error
@@louisdrouard9211 it does?
What, gets stuck in a loop while continually raising the error?
When working with files I think using a context manager is better than using finally to close the file handle.
I like mcoding videos too! Glad you guys watch each other's videos
I watch his for sure, I'm not so sure he watches mine though, his videos are more advanced than mine :)
@@Indently I like having a range of levels. And hey, I'm getting a personal reply from Idently directly! I'm not going to get that from some of the others!
Oh, I also really enjoyed your pandas course on Udemy!!
Sorry, it's very early here, didn't realize how many ! I was using. I need more coffee
so I had some code the looked for data downlinked from space (which is intermittent), and the files names are related to the time the data was collected. So I had a class for the files that ordered them temporary using total_ordering, so I sort the list of candidate files and (in pseudo code)
try:
file is index 0 of sorted list
except an index-error
compute error message like 'file failed to downlink at Thule'
else
get file and compute success message 'file downlinked at McMurdo"
return file to caller
finally:
log the message.
not an if-block in sight, correct message is logged, file is returned or None..program lives to try again. No IF-THEN blocks.
What about the else: after an except?
Nice one. Thanks
finally is for context managers(working with files)
good for writing debugging logs for runtime errors.
I had an issue parsing a text message from a SIM modem. When the signal quality is low it defaults to hex instead of a normal string. The easiest way to check for hex is to convert it to an int. If it throws a value error then it's not hex. But I have no way of knowing if the string will be a normal string or a hex string. So its in a try: int(string) -> convert to string, except: Value error, finally: return string.rstrip(). Because I need the string returned either way.
Why not just :
Try:
...
Except return string
?
I wonder what finally looks like under hood? Maybe whenever the python interpreter enters a try block and checks for a finally and it’s there, it runs the block stores the result then returns it after the other blocks of the try are ran. Something like defer in Go.
Finally is just some bad-ass solid block of code that refuses to not be executed.
Very useful if you want to clean up or close stuff no matter what happened. Just think about an exception you are not handling that you did not expect or came from outside, like KeyboardInterrupt. However, you can also use a with-statement here that should implicitly convert to a try-finally behind the facade.
love your videos
@Indently
request1: please make some videos on useful libraries such as matplotlib,pyautogui,pygame,etc..
Request 2: please make videos on making basic 2d games in python using the turtle module
For making 2d games, turtle is not the way to go. It pales in comparison to the tkinter canvas in terms of speed and ease of use, making it among the worst possible choices for anything more than an image or a simple animation.
@@largewallofbeans9812 No mate, you can use turtle to make games that's easier to code that runs super fast when compared to tkinter. I coded many myself. The codes are too big to copy paste here tho
@@largewallofbeans9812No mate, you can use turtle to make games that's easier to code that runs super fast when compared to tkinter. I coded many myself. They're just too big to copy paste here
@@largewallofbeans9812 No mate, you can use turtle to make games thats easier to code and runs super fast when compared to tkinter. i coded many myself. theyre just too big to copy paste here
that's not even pure python
It is important, that's not a question.
Finally the question is, how good it is? Like how good it is at being finally
I mean I like a try/except/finally video, but using as an example: a non pure function that calculates error codes and modifies state is like teaching 2nd graders modular arithmetic with examples like: Johny has a six shooter but needs to blast 4 he's and 5 she's, how many times does Johnny need to reload? not a good idea.
The finally block is very useful if you want to put a return in the try block but still need to ensure cleanup code executes.
Useful for Rollback operation on db as well.
Most of the time I use finally, i'm not even catching an exception. It's literally just try..finally
Normaly I only use finally when I'm working with Databased, so no matter what happen my connection will be close. Overall, nice explanation ;)
Thank you so much for helping me realize that even after 3 years I'm still a beginner.
Are you still so sure it won't run anyway if you turn off the computer during the except block?
I'm no Scientist, and from personal experience, my scripts need electricity to run, but different dimensions can have different results.
Wait, I can un-break a loop?
The finally block has not many cases where it’s necessary, which is true. It provides irreplaceable functionality, it’s also true. Beginners before finding a right condition to use it are not surprising to describe it as“useless”
Finally is a very useful tool to have the return continue and break quirks ar efunny though. Maybe the pep could warn about it instead of disallowing it since its probably not useful.
Now im wondering how c# handles stuff like this
what if errors were just a return type, and you could match errors like:
x = some_function() # def some_function -> MyError
match x:
case ValueError:
print("handled ValueError")
case OtherError:
print("handled OtherError")
case _:
print("encountered unhandled exception")
More importantly - and I’m surprised not to see it in the video - a code after the whole try/except block won’t be executed if an exception of some other type occurs.
try:
raise TypeError
except ValueError:
…
print('instead of finally') # unreachable
I explained it in the video, it didn't need another example though.
I don't think I would ever use finally over a context manager
It's a bad idea to have multiple returns in general. As a rule of thumb having only on return at the bottom is the best.
I am confused by people saying it's useless. Although I will say that almost everywhere I could use "finally", I would prefer using a "with" statement with a context manager.
nice. the c++ equivalent of this would be destructors running code when the scope it is in is closed :)
Python has context managers that kind of does the same, and is usually a better choice than finally
instead of useless we now have the footgun
Wow, thx for the video. Eyeopening one. Really impressed by unstopable sys.exit() :)
been using python for 5 years now, first time hearing about "finally" lol
short answer: no, it's useful for closing stuff before throwing the exception. like when I'm using pygame, I always put the mainloop inside a try-finally so the window will close rather than just freezing if it throws an exception. haven't watched the video yet, let's see...
This is the same for any other language that uses try...catch...finally.
1:11 😂
Well. I suppose I "finally" understood how it works exactly. (too soon? 🤣)
I use it for cleaning up.. files, db
This is actually quite weird to understand, but it's very useful to know that it isn't useless as I thought.
This sys.exit with finally is a good catch
im sure if it sent a sigkill to itself, finally wouldn't run
Niklaus Wirth, the man who invented exceptions, said they were a bad idea, and not to use them. And that's enough for me.
Still feels like a context manager (`with x() as y:`) is the more appropriate solution 99% of the time
Agree. Finally is just older, but most uses should be replaced by context managers. For example, the video mentions File objects, and they are automatically closed if using the with statement. Using finally is usually a lot more fickle than context managers.
Yeah it doesn't seem like a godsend or anything but it seems kinda useful. it can definitely decrease the lines of code used instead of adding more layers of try and except blocks. and that would make it simpler if you wanted to do more trys and excepts for a larger exception catching
def finalllly():
print('Que tengas un dia fenomenal')
def func():
try:
raise Exception('Exception not Acceptable')
except Exception as e:
print(e)
raise ValueError("Error WITHIN THE ERROR!!")
finally:
finalllly()
def main():
try:
func()
except ValueError:
print('yare yare daze')
raise TypeError
if __name__ == '__main__':
try:
main()
except TypeError as E:
print("--All your training is complete. Now it is up to you, young padawan--")
print("Andy, amigo, el pueblo esta contigo")
"finally" i understood this😅
Finally got it (no pun intended)
I tend to rely on context managers for making sure that files and connections get closed so have gotten out of the habit of using finally. Did not realize how powerful it is (amazed that sys.exit doesn't prevent finally block from running). With context managers for closing files and such I can't think of a lot of use cases for finally.
It should have been called "ensure"
*sigh, opens video about python just for fun*
*fast forwards to middle of the video:*
"the executing order is random here"
*gets confused because every computer program should be deterministic*
*clicks off the video*
finally should be named always_execute
a better name would've been "always:"
My life is a lie 😵
You meant to title the Video "Python is useless", didnt you? 😅
I meant what I wrote :)
Second
First comment 🎉
The most useless thing in Python is else after while True
1K th like
"istg" is more useless than finally
Greast vid, really. However, after watching it I am convinced thast `finally` is not useless -- it's harmfull... :)
no, the if-thens it replaces were harmful.
@@DrDeuteronMaybe we should not be any of them at all ?
This is too beginner level for me.
Unfortunately, RUclips does not have a way to tell that the video is good, but not for me. If anyone from RUclips is reading this, please add that.
Your shorts code editor theme pls
F yt