简体   繁体   中英

Python exceptions and flow control : what exactly is "unexpected"?

  1. I heard using "try except" for flow controlling is something to be avoided, and exceptions should only be used for unexpected cases, so [Code A] is quite obviously discouraged and should use [Code B] instead. Did i understand it correctly?

Most common explanations regarding exceptions are done with file operations, so I'll also do it with file handling :

from pathlib import Path
my_file_path = Path("./something.txt")

####
# Code A : This is a bad practice
####
try :
    content = open (my_file_path, 'r').read()
except FileNotFoundError as e :
    content = ""
    create_file(my_file_path)

####
# Code B : heard using if is a much better practice
####
if my_file_path.is_file() : 
    content = open (my_file_path, 'r').read()
else :
    content = ""
    create_file(my_file_path)

However, my confusion is that what if my program is expecting my_file_path to exist, but exception might occur in some rare cases like a server crash, or de-sync from main server, so to say.

My assumption is that "maybe the file might not exist on first run, so file not existing is a expected flow" should go to if-else statement as i shouldn't control flow with exceptions.

So my question 2 is :

  1. However if i actually intended my program to always "have the file prepared in advance", can I "justify" using exceptions for it(despite the fact that I understand in rare circumstances like a server crash, it might not exist)? or this "rare circumstance" should probably also be handled by if statement?

Quite confused here, or am I just misunderstanding the use of exceptions?

The use of exceptions isn't so much about 'unexpected' errors as it is for errors that deviate from the normal flow of execution.

Also, catching exceptions works on code your code is calling, so it allows you to catch errors that aren't generated in your code more easily and it prevents you from having to know how that inner code works and still be able to deal with problems, ie exceptions.

There's a number of differences between this:

if my_path.is_file():
    with open(str(my_path)) as f:
        success()
else:
    problem()

and this:

try:
    with open(str(my_path)) as f:
        success()
except FileNotFoundError:
    problem()

In the first case, the file may exist when you check for its existence, but there is no guarantee it still exists when you actually open it. To be perfectly safe, you'd still need to catch that exception.

In this case, it's unlikely, but if open() had complicated behaviour, it would be possible that the exception was thrown for a reason that's not captured by .is_file() .

If you're checking for many different problematic outcomes, capturing the relevant exceptions is a fairly clean way to do so. And if you don't deal with the specific exception at this level, some code calling your code may deal with it at a later stage.

That's not to say an if statement is never a good structure for flow control of course, but in this example the success of your code depends on I/O over which you have no direct and total control and in that case, exceptions are almost always the better choice (and you'd have to use them even if you did use the if as well).

Some people will point at the cost of exceptions, but note that exception blocks in Python are very cheap if exceptions aren't raised (and you'd expect them not to be most of the time) https://docs.python.org/2/faq/design.html#how-fast-are-exceptions - if you expect most files you try to open not to exists, that could be a reason to check first.

Try with the try-except for these problems. as:-

try:
    with open(str(my_path)) as f: # first program try to run this
        success()
except FileNotFoundError: #if try doesn't work it goes to here and run.
    problem()

It will try the try block and if cannot it will go to except block and run the given thing. So it will not stop running the code by an error.

You can use

except:

to get all errors and it don't give to stop running the whole program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM