What's the best way to catch exceptions which occur in the *loop header instead of the whole loop or body.
Take the following example
for value in complex_generator(): # throws exceptions I might want to catch
... # do work here - but don't catch any exception
What I don't consider helpful is wrapping the whole loop in a try and except block like so:
try:
for value in complex_generator(): # throws exceptions I might want to catch
... # exceptions raised here will also be caught :(
except Exception:
... # handle exception here
Inspired from golang one might encapsulate the try-except-block and always return two elements:
def wrapper(iterable):
try:
for value in iterable:
yield value, None
except Exception as e:
yield None, e
for value, err in wrapper(complex_generator()):
if err != None:
... # handle error
else:
... # do work but don't catch any exception here
This however doesn't feel pythonic and a type checker would also require a additional check. Any ideas?
CodePudding user response:
Get the generator first?
try:
cg = complex_generator()
except Exception as e:
cg = [] # could alternatively have a success boolean here, and wrap the `for` loop below in an `if`
for value in cg:
...
CodePudding user response:
There are two levels of errors: Those that the generator throws, and those that your worker code throws. I would use a nested try
:
try:
for value in complex_generator():
try:
# do work here
except ValueError:
# catch ValueError and keep going
except OtherError:
# catch OtherError and keep going
# any other error breaks the loop
except ExpectedGeneratorError:
# handle generator exception here
except:
# handle more errors
You could extract the inner part into a worker function to keep things tidy.