Pythonic way to try reading a file and in case of exception fallback to alternate file

Question:

What is the Pythonic way to try reading a file and if this read throws an exception fallback to read an alternate file?

This is the sample code I wrote, which uses nested tryexcept blocks. Is this pythonic:

try:
    with open(file1, "r") as f:
        params = json.load(f)
except IOError:
    try:
        with open(file2, "r") as f:
            params = json.load(f)
    except Exception as exc:
        print("Error reading config file {}: {}".format(file2, str(exc)))
        params = {}
except Exception as exc:
    print("Error reading config file {}: {}".format(file1, str(exc)))
    params = {}
Asked By: nitin_cherian

||

Answers:

You can check if file1 exists first, and then decide which file to open. It will shorten the code and avoid repeating the try -- catch clause. I believe it is more pythonic, however note that you need to import os in your module for this to work.
It can be something like:

fp = file1 if os.path.isfile(file1) else file2
if os.path.isfile(fp):
    try:
        with open(fp, "r") as f:
            params = json.load(f)
    except Exception as exc:
        print("Error reading config file {}: {}".format(fp, str(exc)))
            params = {}
else:
    print 'no config file'
Answered By: Chen A.

Although I’m not exactly certain whether this is pythonic or not, perhaps something like:

file_to_open = file1 if os.path.isfile(file1) else file2
Answered By: Wiggy A.

For two files the approach is in my opinion good enough.

If you had more files to fallback I would go with a loop:

for filename in (file1, file2):
    try:
        with open(filename, "r") as fin:
            params = json.load(f)
        break
    except IOError:
        pass
    except Exception as exc:
        print("Error reading config file {}: {}".format(filename, str(exc)))
        params = {}
        break
else:   # else is executed if the loop wasn't terminated by break
    print("Couldn't open any file")
    params = {}
Answered By: MSeifert

I recommend using pathlib.Path for this.

from pathlib import Path

path1 = Path(file1)
path2 = Path(file2)

path = path1 if path1.exists() else path2

with path.open('r') as f:
   params = json.load(f)

You can add additional error checking on whether path2 exists or not if desired.

Answered By: gavinest