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对该异常不做任何操作。这不回答任何问题,它只复制了原始问题的一段代码。