4

Problem:

I have code that looks for a file and open it. By default it looks for file that starts with ####### (each # being a number).

Problem is sometimes the file name is ##-##### and other times #####.

I would like a way if the file cannot be found try looking for the other two ways the file could be written.

An IOError exception happens when the file is not found. What I was thinking was to have an except statement that says:

except File2:
    Look for ##### in  myfindFileFunction()
    if file is still not found run except File3
except File3:
    Look for ##-#### in myfindFileFuction()
except:
    print "File not found"

What I am not sure of is how to set up custom exception to work this way, and/or if there is a more pythonic way to do this altogether...

Would setting up a pattern or the three possible file names and iterate thought each until the file is found work better?

Tristan Forward
  • 3,304
  • 7
  • 35
  • 41

3 Answers3

5

Using try/except is indeed a very pythonic (and fast) way of doing things.

You have to weigh not only if it's pythonic, but what impact does that approach has in terms of readability. Will you still understand the code quickly when you look at it again in 6 months? Will somebody else?

I usually make sure that slightly complex try/except clauses to handle this kind of things are well commented. Asides from that... it's a perfectly reasonable way of doing it.

Also, to put your mind at ease regarding performance, a common concern when one is deciding between two approaches, take a look here: Python if vs try-except and you'll see that try/except constructs are fast in Python... really fast.

Community
  • 1
  • 1
pcalcao
  • 15,789
  • 1
  • 44
  • 64
  • 1
    Depending on what/how many files are in the directory, this could be much slower than a more complex regex run against each file name. `myFindFileFunction()` implies that each exception case will iterate over the files in a given directory, leading to worst case looping over every file name n times (n being the number of candidate file name patterns). By contrast, a one-size-fits-all-regex-based solution should only have to iterate over the file names in the directory once, even in worst case. – Silas Ray Jul 25 '12 at 16:49
3

no custom exception needed

import errno

try:
    open('somefile')
except IOError as e:
    if e.errno == errno.ENOENT:
        open('someotherfilename')
    else:
        raise e

(this is on *nix- im not sure if you're using windows)

tMC
  • 18,105
  • 14
  • 62
  • 98
  • If I am reading this correctly, this only supports looking for one other type of file not two other types – Tristan Forward Jul 25 '12 at 22:47
  • @user765015 no reason you couldn't keep nesting it- If the number of different permutations is finite. – tMC Jul 26 '12 at 12:47
1

It's easy enough to define your own exceptions -- just create a class derived from Exception. The doco is clear.

However creating separate exceptions per file type, or any exception at all, doesn't seem necessary. You could do something like:

files = ('#######', "##-#####', '#####')

fh = None
for f in files:
    try:
        fh = open(f)
        break
    except IOError as e:
        if e.errno in (errno.ENOENT,):
            pass
        else:
            raise

if not fh:
    ## all three tries failed

The use of if around e.errno lets you decide which IO errors mean go on to the next file and which are errors you want to know about . File does not exists (errno.ENOENT) means try next file. But others like 'Too many files open' (errno.ENFILE) probably need a different response.

Chris Johnson
  • 20,650
  • 6
  • 81
  • 80