Should I raise ValueError or OSError for non-existent file arguments?
当程序接收到不存在或不是目录的文件名参数时,我想引发一个错误。但是什么错误被认为是最佳实践?
我知道ValueError经常被用来表示无效的论点(我已经看到了几个关于它的问题)。我还了解到,特别是在对python 3.3(pep 3151)中的异常进行了重组之后,对于与系统交互相关的问题,OSError是"捕获所有"类别。
所以,我有一个程序需要一个文件名参数。如果调用者提供的名称不存在,或者存在,但是是一个目录,我应该引发什么错误?这是一个错误的论点,因此似乎ValueError适用;但如果我试图将其作为文件读取,我将得到OSError,那么不应该为了一致性而返回它吗?
- 在这一点上你需要提出什么吗?如果文件是否存在确实很重要,那么很可能还会有另一个异常出现。换言之:你提出的理由是什么?
- 如果不打算捕获异常,这只是一个美学问题;但是我追求这一原则,那么让我们假设这是一个长期运行的程序,错误将被捕获,模块将使用新的参数(例如,交互)进行调用。
- 这在Python中有点反模式:你应该请求宽恕,而不是许可。因此,如果您不打算对错误做任何事情,只需忽略它,让将要崩溃的东西崩溃,并让产生的异常冒泡到调用方。如果你正在编写一个库,我会在这个规则中添加一个例外(不打算使用双关语),在这种情况下,你可能需要自己的异常层次结构,这样用户就可以捕获来自lib的错误(例如,像requests有HTTPError)。
- EAFP…lbyl只是两个相互竞争的思想流派,也不是一个反模式的…虽然一般Python赞成EAFP
这真的很重要吗?(我假设您没有捕捉到这个异常,它纯粹是为查看终端输出的个人提供信息)操作系统不会看到这些异常,我只是
1
| raise Exception("Invalid Arguments, expected a file that exists not %r"%(filename)) |
或者让它在尝试自然打开文件时失败,甚至
- 如果我让它自然地打开文件,我会得到一个OsCurror…因此,这个问题。我更喜欢"三思而后行"的方法,但我有一个例外,那就是不应该依赖于我的编码风格。
- 所以你问你是否应该抓住它并引发一个不同的操作系统错误?或者,如果您应该执行与fh = open(some_file)几乎相同的if not os.exists(fname): raise OSError("File Doesnt exist"),除非在文件句柄确实存在的情况下您不会得到它
- 好吧,如果我真的提高了误差,结果是相似的,但是有了valueerror,结果就不同了。正如我所写,这就是考虑奥瑟罗的动机。
- 在这两种情况下,程序都以非零退出代码退出…操作系统不知道这些错误类型中的任何一种…你所要做的就是向用户表达问题是什么…唯一需要担心的是,如果您计划捕获错误,以便根据错误类型区分不同的逻辑
- 谢谢,但我知道,我在一个评论中提到了这个问题。我提出这个问题的动机很大程度上是概念上的,但是让我们假设这个错误会被捕获,否则这个问题实际上是毫无意义的。但我并不是在寻找"毫无意义"的答案。
- 好吧,如果你要抓住它,我会引发一个OSError,甚至一个自定义的fileNotFound异常…但如果这就是为什么你不让正常的错误冒出来,被捕捉到你的第二个错误会被捕捉到…我不是一个聪明的人(或故意刁难),我发誓,这些是你应该考虑的事情
- 我可能想自己提出错误的一个原因是,如果我真的应该提出valueerror。从阅读PEP来看,选择(和设计)异常的最重要标准似乎是人们可能想要捕捉哪些异常集合。我会把它和其他与论点相关的错误(因此:valueerror)联系起来,但是我写了这个问题,这样我就可以从集体经验中获益……