user8087992
user8087992

Reputation:

Return encountered error from function

How would I return the error received during a function call back to main?

I've got something simple such as:

def check(file):
    if not os.path.exists(file):  # returns false by itself, but I want error
        return -1

When called, it just returns to the calling .py and the program ends. But I am trying to return what happened (i.e. the file does not exist). Is raising an exception more appropriate?

Upvotes: 0

Views: 837

Answers (3)

aneroid
aneroid

Reputation: 16007

(As an alternative to my previous answer.)

Another more correct way to do the check() if you want to explicitly check before doing anything else - use os.stat() which doesn't actually open the file:

import os

def check(file):
    try:
        os.stat(file)
        # continue doing something here or 
        # return to the function which wants to open file
    except FileNotFoundError as e:
        # log error, print error, or.. etc.
        raise e  # and then re-raise it

Result of this version is:

>>> check('xyz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in check
  File "<stdin>", line 3, in check
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'xyz'
>>>

Note that the error is a bit different here vs the prev: [Errno 2] No such file or directory: 'xyz'

Upvotes: 0

aneroid
aneroid

Reputation: 16007

If you do want to raise an exception instead of returning -1 when the file doesn't exist, you could skip the check() and go directly to open() or whatever you actually want to do with the file.

The correct way to actually raise the exception is to let it get raised. So do:

def check_and_open(file):
    # raises FileNotFoundError automatically
    with open('xyz', 'r') as fp:
        fp.readlnes()  # or whatever

And if you do want to explicitly check before you open, this will raise the actual error object:

def check(file):
    try:
        with open(file, 'r') as fp:
            # continue doing something with `fp` here or 
            # return `fp` to the function which wants to open file
            pass
    except FileNotFoundError as e:
        # log error, print error, or.. etc.
        raise e  # and then re-raise it

Result of this version is:

>>> check('xyz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in check
  File "<stdin>", line 3, in check
FileNotFoundError: [Errno 2] No such file or directory: 'xyz'
>>>

Also, note that just doing raise FileNotFoundError(file), like in another answer provided, breaks how FileNotFoundError actually raises:

Raising explicitly (the filename gets considered as the err message):

>>> raise FileNotFoundError('xyz')
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError: xyz
>>>

How it's actually raised by Python:

>>> fp = open('xyz', 'r')
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'xyz'
>>>
>>> # or with `with`:
... with open('xyz', 'r') as fp:
...     fp.readlnes()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'xyz'
>>>

Upvotes: 1

bakatrouble
bakatrouble

Reputation: 1844

You could raise an exception (FileNotFoundError is used in built-in libraries), although if you'll try to use non-existent file you'll get FileNotFoundError exception raised by default.

Then, when using this function, handle your exception:

import os

def check(file):
    if not os.path.exists(file):
        raise FileNotFoundError(file)

if __name__ == '__main__':
    try:
        check(os.path.join('foo', 'bar'))
    except FileNotFoundError:
        print('File was not found')

Upvotes: 0

Related Questions