Python 忽略生成器中的异常
通过使用Python 忽略生成器中的异常,python,exception,for-loop,generator,Python,Exception,For Loop,Generator,通过使用os.walk()如下遍历文件夹: for subdir, dirs, files in os.walk(path): do something... 将引发异常:UnicodeDecodeError,我想忽略该异常并继续,我尝试了以下操作: try: for subdir, dirs, files in os.walk(path): do something... except Exception, e: logging.exception(e
os.walk()
如下遍历文件夹:
for subdir, dirs, files in os.walk(path):
do something...
将引发异常:UnicodeDecodeError
,我想忽略该异常并继续,我尝试了以下操作:
try:
for subdir, dirs, files in os.walk(path):
do something...
except Exception, e:
logging.exception(e)
continue # this continue is illegal
正如注释所述,异常部分中的continue
是一个语法错误。有没有办法忽略异常并继续遍历
异常是从
os.walk()
引发的,因此将try/except
放在for
中无法捕获异常。os.walk()
将返回一个python生成器,如何捕获其中的异常?更新:
我最初认为错误是由do something…
code引起的。由于它实际上是由os.walk引发的,因此您需要做一些不同的事情:
walker = os.walk(path)
while True:
try:
subdir, dirs, files = next(walker)
except UnicodeDecodeError as e:
logging.exception(e)
continue
except StopIteration:
break
do something...
基本上,这是利用了os.walk
返回。这允许我们调用它,从而在每个步骤中控制迭代
subdir,dirs,files=next(walker)
行尝试推进迭代。如果出现UnicodeDecodeError
,则会记录该错误,然后我们继续下一步。如果引发了一个StopIteration
异常,这意味着我们已经完成了对目录树的遍历。所以,我们打破了循环
由于
continue
需要在循环中,因此您还需要将try/except
块移动到循环中:
for subdir, dirs, files in os.walk(path):
try:
do something...
except Exception, e:
logging.exception(e)
continue # this continue is *not* illegal
此外,做:
except Exception, e:
已被弃用。您应该使用作为关键字来代替,
:
except Exception as e:
在执行此操作时,应将通用的异常
替换为特定的UnicodeDecodeError
:
except UnicodeDecodeError as e:
您应该始终尝试捕获最具体的异常。否则,您可能会意外发现一个您无意处理的异常。在使用Beautiful Soup迭代链接时,我也遇到过类似的情况。这是我为此编写的代码:
for subdir, dirs, files in os.walk(path):
try:
do something...
except Exception, e:
logging.exception(e)
continue # this continue is illegal
class suppressed_iterator:
def __init__(self, wrapped_iter, skipped_exc = Exception):
self.wrapped_iter = wrapped_iter
self.skipped_exc = skipped_exc
def __next__(self):
while True:
try:
return next(self.wrapped_iter)
except StopIteration:
raise
except self.skipped_exc:
pass
class suppressed_generator:
def __init__(self, wrapped_obj, skipped_exc = Exception):
self.wrapped_obj = wrapped_obj
self.skipped_exc = skipped_exc
def __iter__(self):
return suppressed_iterator(iter(self.wrapped_obj), self.skipped_exc)
例如:
class IHateThirteen:
''' Throws exception while iterating on value 13 '''
def __init__(self, iterable):
self.it = iter(iterable)
def __iter__(self):
return self
def __next__(self):
v = next(self.it)
if v == 13:
raise ValueError('I hate 13!')
return v
# Outputs [10, 11, 12, 14, 15]
exception_at_thirteen = IHateThirteen([10, 11, 12, 13, 14, 15])
print(list(suppressed_generator(exception_at_thirteen)))
# Raises ValueError
exception_at_thirteen = IHateThirteen([10, 11, 12, 13, 14, 15])
print(list(exception_at_thirteen))
您可以使用上述代码修复代码:
for subdir, dirs, files in suppressed_generator(os.walk(path)):
do something...
如果需要,可以对上述代码进行更多扩展,以针对每个跳过的异常类型进行回调,但在这种情况下使用它可能更具python风格。捕获特定的UnicodeDecodeError也比捕获可能引发的任何常规异常“do something”要好。从os.walk()
抛出的异常不在for
循环中,因此try/except对该异常不做任何操作。这不回答任何问题,它只复制了原始问题的一段代码。