Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Error-Checking Standard Practice

I have a question regarding error checking in Python. Let's say I have a function that takes a file path as an input:

def myFunction(filepath):
    infile = open(filepath)
    #etc etc...

One possible precondition would be that the file should exist.

There are a few possible ways to check for this precondition, and I'm just wondering what's the best way to do it.

i) Check with an if-statement:

if not os.path.exists(filepath):
    raise IOException('File does not exist: %s' % filepath)

This is the way that I would usually do it, though the same IOException would be raised by Python if the file does not exist, even if I don't raise it.

ii) Use assert to check for the precondition:

assert os.path.exists(filepath), 'File does not exist: %s' % filepath

Using asserts seems to be the "standard" way of checking for pre/postconditions, so I am tempted to use these. However, it is possible that these asserts are turned off when the -o flag is used during execution, which means that this check might potentially be turned off and that seems risky.

iii) Don't handle the precondition at all

This is because if filepath does not exist, there will be an exception generated anyway and the exception message is detailed enough for user to know that the file does not exist


I'm just wondering which of the above is the standard practice that I should use for my codes.

like image 272
chaindriver Avatar asked May 16 '10 12:05

chaindriver


People also ask

Is try and except good practice?

The reason to use try/except is when you have a code block to execute that will sometimes run correctly and sometimes not, depending on conditions you can't foresee at the time you're writing the code.

How do I get out of TRY except?

Use an else clause right after the try-except block. The else clause will get hit only if no exception is thrown. The else statement should always precede the except blocks. In else blocks, you can add code which you wish to run when no errors occurred.


2 Answers

If all you want to do is raise an exception, use option iii:

def myFunction(filepath):
    with open(filepath) as infile:
        pass

To handle exceptions in a special way, use a try...except block:

def myFunction(filepath):
    try:
        with open(filepath) as infile:
            pass
    except IOError:
        # special handling code here

Under no circumstance is it preferable to check the existence of the file first (option i or ii) because in the time between when the check or assertion occurs and when python tries to open the file, it is possible that the file could be deleted, or altered (such as with a symlink), which can lead to bugs or a security hole.

Also, as of Python 2.6, the best practice when opening files is to use the with open(...) syntax. This guarantees that the file will be closed, even if an exception occurs inside the with-block.

In Python 2.5 you can use the with syntax if you preface your script with

from __future__ import with_statement
like image 146
unutbu Avatar answered Oct 06 '22 19:10

unutbu


Definitely don't use an assert. Asserts should only fail if the code is wrong. External conditions (such as missing files) shouldn't be checked with asserts.

As others have pointed out, asserts can be turned off.

The formal semantics of assert are:

  1. The condition may or may not be evaluated (so don't rely on side effects of the expression).

  2. If the condition is true, execution continues.

  3. It is undefined what happens if the condition is false.

More on this idea.

like image 41
Ned Batchelder Avatar answered Oct 06 '22 20:10

Ned Batchelder