在循环头中捕获异常但在循环体中不捕获
Catch exception in loop head but not in loop body
捕获发生在 *loop 头而不是整个循环或主体中的异常的最佳方法是什么。
举下面的例子
for value in complex_generator(): # throws exceptions I might want to catch
... # do work here - but don't catch any exception
我认为没有帮助的是将整个循环包装在 try 和 except 块中,如下所示:
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
受 golang 的启发,可以封装 try-except-block 并且总是 return 两个元素:
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
然而,这感觉不像 pythonic,类型检查器也需要额外检查。有什么想法吗?
先获取发电机?
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:
...
有两个级别的错误:生成器抛出的错误和您的工作程序代码抛出的错误。我会使用嵌套的 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
您可以将内部部分提取到辅助函数中以保持整洁。
我仍然认为@Tomalak 的回答是解决这个问题的最pythonic 方法。但是我想分享我最终使用的解决方案,因为 complex_generator
和循环体都可能引发相同的异常。
from typing import Iterable, Iterator, TypeVar
T = TypeVar("T")
def wrapper(iterable: Iterable[T]) -> Iterator[T | Exception]:
try:
for value in iterable:
yield value
except Exception as e:
yield e
for value in wrapper(complex_generator()):
if isinstance(value, Exception):
handle_generator_error(value)
else:
try:
process(value)
except Exception as e:
handle_loop_error(e)
注意:对于更复杂的场景,可以使用 match
(structural pattern matching) 并将正文错误处理移动到 process
函数中。
捕获发生在 *loop 头而不是整个循环或主体中的异常的最佳方法是什么。
举下面的例子
for value in complex_generator(): # throws exceptions I might want to catch
... # do work here - but don't catch any exception
我认为没有帮助的是将整个循环包装在 try 和 except 块中,如下所示:
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
受 golang 的启发,可以封装 try-except-block 并且总是 return 两个元素:
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
然而,这感觉不像 pythonic,类型检查器也需要额外检查。有什么想法吗?
先获取发电机?
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:
...
有两个级别的错误:生成器抛出的错误和您的工作程序代码抛出的错误。我会使用嵌套的 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
您可以将内部部分提取到辅助函数中以保持整洁。
我仍然认为@Tomalak 的回答是解决这个问题的最pythonic 方法。但是我想分享我最终使用的解决方案,因为 complex_generator
和循环体都可能引发相同的异常。
from typing import Iterable, Iterator, TypeVar
T = TypeVar("T")
def wrapper(iterable: Iterable[T]) -> Iterator[T | Exception]:
try:
for value in iterable:
yield value
except Exception as e:
yield e
for value in wrapper(complex_generator()):
if isinstance(value, Exception):
handle_generator_error(value)
else:
try:
process(value)
except Exception as e:
handle_loop_error(e)
注意:对于更复杂的场景,可以使用 match
(structural pattern matching) 并将正文错误处理移动到 process
函数中。