对于不存在的文件参数,我应该抛出ValueError还是OSError?

4
当程序接收到不存在或者不是一个目录的文件名参数时,我希望引发一个错误。但是,什么错误被认为是最佳实践呢?
我知道在Python中,ValueError通常用于表示无效参数(我已经看到了关于此问题的几个 问题)。我也知道,特别是在Python3.3重组异常(PEP 3151)之后,OSError是与系统交互相关问题的万能类型。
因此,如果程序期望一个文件名参数,而调用者提供的名称不存在,或者存在但是是一个目录,那么应该引发什么错误呢?这是一个不正确的参数,所以似乎应该使用ValueError;但是如果我尝试将其作为文件读取,我将得到一个OSError-- 因此,出于一致性的考虑,是否应该返回它呢?

1
你现在需要抛出 任何东西 吗?如果文件是否存在很重要,那么未来可能会引发另一个异常。换句话说:你抛出的用例是什么? - Thomas Orozco
如果异常不打算被捕获,那只是一个审美问题;但我追求的是背后的原则,所以让我们假设这是一个长时间运行的程序,错误将被捕获并且模块将被调用使用新的参数(例如,交互式地)。 - alexis
1
这在Python中有点反模式:你应该请求宽恕,而不是许可。因此,如果您不打算对错误采取任何措施,只需忽略它,让任何可能崩溃的东西崩溃,并让结果异常冒泡到调用者。如果您正在编写库,则可以将异常(无意双关语)添加到此规则中,这样您可能希望拥有自己的异常层次结构,以便用户可以捕获来自您的库的错误(例如,像requests具有HTTPError)。 - Thomas Orozco
EAFP(Easier to Ask for Forgiveness than Permission)和LBYL(Look Before You Leap)只是两种相互竞争的思维方式,它们都不是反模式...尽管一般来说,Python更倾向于采用EAFP。 - Joran Beasley
1个回答

2

这真的很重要吗?(我假设你没有捕获这个异常,它只是为了一个人查看终端输出的信息目的)操作系统不会将任何内容视为异常,所以我只需要...

raise Exception("Invalid Arguments, expected a file that exists not %r"%(filename))

或者让它在尝试自然打开文件时失败。

1
如果我让它自然地尝试打开文件,我会得到一个OSError...因此有这个问题。我更喜欢先看后跳的方法,但我有一种感觉异常不应该依赖于我的编码风格。 - alexis
如果我引发OSError,结果是类似的,但是对于ValueError则不是。这就是我考虑OSError的动机,正如我所写的那样。 - alexis
在这两种情况下,程序都以非零退出代码退出...操作系统对这些错误类型一无所知...你想要做的就是向用户表达问题所在...唯一需要担心的是如果您计划捕获错误,以便根据错误类型区分不同的逻辑。 - Joran Beasley
谢谢,但我知道,在问题下的评论中已经提到了这一点。我提出问题的动机在很大程度上是概念性的,但让我们假设错误将被捕获,否则问题确实毫无意义。但我不希望“毫无意义”作为答案。 - alexis
1
如果你要捕获它,我会引发一个OSError甚至是自定义的FileNotFound异常...但如果是这种情况,为什么不让正常的OSError上升并在你第二个错误被捕获的级别上被捕获呢...我不是故意找麻烦或者刻意表现聪明,我发誓,这些是你应该考虑的事情。 - Joran Beasley
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接