首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >捕获FileNotFoundError并继续读取文件

捕获FileNotFoundError并继续读取文件
EN

Stack Overflow用户
提问于 2022-10-19 11:51:09
回答 2查看 62关注 0票数 1

我正在使用pathlib执行文件操作,大致如下:

代码语言:javascript
复制
for path in Path.cwd().glob("*.ipynb"):
    print(path)

问题是,这些文件位于外部驱动器上,往往会随机断开连接。因此,glob迭代器抛出一个FileNotFoundError。这是对正在发生的事情的模拟:

代码语言:javascript
复制
def hdd_disconnection_mockup():
    for i in range(3):
        if i == 1:
            raise FileNotFoundError
        yield f"Untitled{i}.ipynb"
代码语言:javascript
复制
>>> for path in hdd_disconnection_mockup():
        print(path)
Untitled0.ipynb
FileNotFoundError:

我想捕捉这个异常并继续执行for循环。

到目前为止,我已经尝试了以下几点:

代码语言:javascript
复制
def catch_filenotfounderror(glob):
    try:
        yield next(glob)
    except FileNotFoundError:
        pass

不会引发任何异常,但这并不会阻止glob迭代器中断for循环。

代码语言:javascript
复制
>>> for path in catch_filenotfounderror(hdd_disconnection_mockup()):
        print(path)
Untitled0.ipynb

预期输出是

代码语言:javascript
复制
Untitled0.ipynb
Untitled2.ipynb
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-19 17:02:02

@Michael Dorner指出:

当生成器抛出异常时,它将退出,您不能继续使用它生成的项。

因此,不可能处理生成器之外的异常。

解决方案

最后,我通过将glob迭代器转换为元组,务实地解决了这个问题。这样,如果在读取路径时出现问题,则在开始时,即进入for循环之前。然后,在for循环中处理异常。

代码语言:javascript
复制
ipynb_paths = Path.cwd().glob("*.ipynb")
for path in tuple(ipynb_paths):
    try:
        # read from path ...
    except FileNotFoundError:
        continue

失败方法

为了记录在案,我尝试在抛出FileNotFoundError之前创建迭代器的“安全副本”。这个想法是,如果异常发生,我可以让电脑睡一会儿,希望硬盘重新连接,然后用安全拷贝重试。

代码语言:javascript
复制
def catch_filenotfounderror(glob):
    while True:
        glob, safety_glob = tee(glob, 2)
        try:
            yield next(glob)
        except FileNotFoundError:
            sleep(0.1)  # Give some time to the HDD to reconnect
            glob = safety_glob
        except StopIteration:
            break

不幸的是,安全生成器似乎链接到了它的原始版本,因为它在发生StopIteration的同一时刻引发了一个FileNotFoundError异常。

在这里,这是一个证明这种行为的例子。

代码语言:javascript
复制
class Gen:
    exception_thrown = False
    @classmethod
    def go(cls):
        yield "one"
        if not cls.exception_thrown:
            cls.exception_thrown = True
            raise Exception
        yield "two"

g1, g2 = tee(Gen.go(), 2)
代码语言:javascript
复制
>>> while True:
        print(next(g1))
'one'
Exception:
代码语言:javascript
复制
>>> while True:
        print(next(g2))
'one'
StopIteration:

以下是我所期望的行为,假设用tee制作的副本完全断开连接:

代码语言:javascript
复制
>>> for i in Gen.go():
        print(i)
'one'
Exception:
>>> for i in Gen.go():
        print(i)
'one'
'two'
票数 0
EN

Stack Overflow用户

发布于 2022-10-19 13:43:08

我认为这是不可能的:当生成器抛出异常时,它就会退出,并且您不能继续使用它生成的项。

由于您无论如何都不处理异常,所以您可能可以在读取之前检查该文件,以避免FileNotFoundError

代码语言:javascript
复制
from pathlib import Path

my_file = Path('/path/to/file')
if my_file.exists():
    # read file
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74124836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档