Python exception handling in list comprehension

2019-02-07 00:19发布

问题:

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.

回答1:

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.



回答2:

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]


回答3:

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