17

I have a Python function called plot_pdf(f) that might throw an error. I use a list comprehension to iterate over a list of files on this function:

[plot_pdf(f) for f in file_list]

I want to use try-except block to skip any possible errors during the iteration loop and continue with the next file. So is the following code correct way to do the exception handling in Python list comprehension?

try:
    [plot_pdf(f) for f in file_list]  # using list comprehensions
except:
    print ("Exception: ", sys.exc_info()[0])
    continue

Will the above code terminate the current iteration and go to the next iteration? If I can't use list comprehension to catch errors during iteration, then I have to use the normal for loop:

for f in file_list:
    try:
        plot_pdf(f)
    except:
        print("Exception: ", sys.exc_info()[0])
        continue

I want to know if I can use try-except to do exception handling in list comprehension.

tonga
  • 11,749
  • 25
  • 75
  • 96

3 Answers3

19
try:
    [plot_pdf(f) for f in file_list]  # using list comprehensions
except:
    print ("Exception: ", sys.exc_info()[0])
    continue

If plot_pdf(f) throws an error during execution of comprehension, then, it is caught in the except clause, other items in comprehension won't be evaluated.

It is not possible to handle exceptions in a list comprehension, for a list comprehension is an expression containing other expression, nothing more (i.e. no statements, and only statements can catch/ignore/handle exceptions).

Function calls are expression, and the function bodies can include all the statements you want, so delegating the evaluation of the exception-prone sub-expression to a function, as you've noticed, is one feasible workaround (others, when feasible, are checks on values that might provoke exceptions, as also suggested in other answers).

More here.

Community
  • 1
  • 1
kiriloff
  • 25,609
  • 37
  • 148
  • 229
  • Thanks. This helps me to understand more about the list comprehension. – tonga May 17 '13 at 14:32
  • @kiriloff, is there a technical reason why future version of comprehensions cannot include an `except` clause? eg `[x[1] for x in list except IndexError pass]` – alancalvitti Jun 14 '19 at 20:46
13

You're stuck with your for loop unless you handle the error inside plot_pdf or a wrapper.

def catch_plot_pdf(f):
    try:
        return plot_pdf(f)
    except:
        print("Exception: ", sys.exc_info()[0])

[catch_plot_pdf(f) for f in file_list]
Daenyth
  • 35,856
  • 13
  • 85
  • 124
  • I have some exception handling inside `plot_pdf()`. But that doesn't catch all errors. So I want to use exception handling outside the list comprehension. I just want to know if the try-except block takes any effects on list comprehension. If not, then I can only use regular for loop to catch out-most exceptions. – tonga May 17 '13 at 14:12
  • 1
    So use a regular for loop. – Benjamin Hodgson May 17 '13 at 14:16
6

You could create a catch object

def catch(error, default, function, *args, **kwargs):
    try: return function(*args, **kwargs)
    except error: return default

Then you can do

# using None as default value
result (catch(Exception, None, plot_pdf, f) for f in file_list)  

And then you can do what you want with the result:

result = list(result)  # turn it into a list
# or
result = [n for n in result if n is not None]  # filter out the Nones

Unfortunately this will not be even remotely C speed, see my question here

Community
  • 1
  • 1
vitiral
  • 8,446
  • 8
  • 29
  • 43