Python 我应该总是在 `except` 语句中指定异常类型吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14797375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:27:55  来源:igfitidea点击:

Should I always specify an exception type in `except` statements?

pythonexceptionpep8

提问by HorseloverFat

When using PyCharm IDE the use of except:without an exception type triggers a reminder from the IDE that this exception clause is Too broad.

使用 PyCharm IDE 时,使用except:无异常类型会触发来自 IDE 的提醒,该异常子句是Too broad.

Should I be ignoring this advice? Or is it Pythonic to always specific the exception type?

我应该忽略这个建议吗?或者总是指定异常类型是 Pythonic 吗?

采纳答案by babbageclunk

It's almost always better to specify an explicit exception type. If you use a naked except:clause, you might end up catching exceptions other than the ones you expect to catch - this can hide bugs or make it harder to debug programs when they aren't doing what you expect.

指定显式异常类型几乎总是更好。如果您使用裸except:子句,您最终可能会捕捉到您期望捕捉到的异常之外的异常 - 这可能会隐藏错误或在程序未按照您的预期执行时使调试变得更加困难。

For example, if you're inserting a row into a database, you might want to catch an exception that indicates that the row already exists, so you can do an update.

例如,如果您要向数据库中插入一行,您可能希望捕获一个异常,表明该行已存在,以便您可以进行更新。

try:
    insert(connection, data)
except:
    update(connection, data)

If you specify a bare except:, you would also catch a socket error indicating that the database server has fallen over. It's best to only catch exceptions that you know how to handle - it's often better for the program to fail at the point of the exception than to continue but behave in weird unexpected ways.

如果您指定一个 bare except:,您还会发现一个套接字错误,表明数据库服务器已经倒下。最好只捕获您知道如何处理的异常 - 程序在异常点失败通常比继续但以奇怪的意外方式运行更好。

One case where you might want to use a bare except:is at the top-level of a program you need to always be running, like a network server. But then, you need to be very careful to log the exceptions, otherwise it'll be impossible to work out what's going wrong. Basically, there should only be at most one place in a program that does this.

您可能想要使用裸机的一种情况except:是在您需要始终运行的程序的顶层,例如网络服务器。但是,您需要非常小心地记录异常,否则将无法弄清楚出了什么问题。基本上,程序中最多应该只有一个地方可以执行此操作。

A corollary to all of this is that your code should never do raise Exception('some message')because it forces client code to use except:(or except Exception:which is almostas bad). You should define an exception specific to the problem you want to signal (maybe inheriting from some built-in exception subclass like ValueErroror TypeError). Or you should raise a specific built-in exception. This enables users of your code to be careful in catching just the exceptions they want to handle.

其推论这一切是你的代码不应该这样做raise Exception('some message'),因为它迫使客户端代码使用except:(或except Exception:这是几乎一样糟糕)。您应该定义一个特定于您想要发出信号的问题的异常(可能继承自某些内置异常子类,如ValueErrorTypeError)。或者您应该引发特定的内置异常。这使您的代码用户能够小心地捕获他们想要处理的异常。

回答by Ulrich Eckhardt

You will also catch e.g. Control-C with that, so don't do it unless you "throw" it again. However, in that case you should rather use "finally".

你也会用它来捕捉例如 Control-C,所以除非你再次“抛出”它,否则不要这样做。但是,在这种情况下,您应该使用“finally”。

回答by Pavel Anossov

Always specify the exception type, there are many types you don't want to catch, like SyntaxError, KeyboardInterrupt, MemoryErroretc.

始终指定的异常类型,也有很多种类,你不想抓,像SyntaxErrorKeyboardInterruptMemoryError等等。

回答by asheeshr

You should not be ignoring the advice that the interpreter gives you.

您不应忽视口译员给您的建议。

From the PEP-8Style Guide for Python :

来自Python 的 PEP-8风格指南:

When catching exceptions, mention specific exceptions whenever possible instead of using a bare except: clause.

For example, use:

捕获异常时,尽可能提及特定的异常,而不是使用一个空的 except: 子句。

例如,使用:

 try:
     import platform_specific_module 
 except ImportError:
     platform_specific_module = None 

A bare except: clause will catch SystemExit and KeyboardInterrupt exceptions, making it harder to interrupt a program with Control-C, and can disguise other problems. If you want to catch all exceptions that signal program errors, use except Exception: (bare except is equivalent to except BaseException:).

A good rule of thumb is to limit use of bare 'except' clauses to two cases:

If the exception handler will be printing out or logging the traceback; at least the user will be aware that an error has occurred. If the code needs to do some cleanup work, but then lets the exception propagate upwards with raise. try...finally can be a better way to handle this case.

一个空的 except: 子句将捕获 SystemExit 和 KeyboardInterrupt 异常,使得用 Control-C 中断程序变得更加困难,并且可以掩盖其他问题。如果要捕获所有表示程序错误的异常,请使用except Exception:(bare except 等价于except BaseException:)。

一个好的经验法则是将裸“except”子句的使用限制为两种情况:

如果异常处理程序将打印或记录回溯;至少用户会意识到发生了错误。如果代码需要做一些清理工作,然后让异常随着 raise 向上传播。try...finally 可以成为处理这种情况的更好方法。

回答by Tony Hopkinson

Not specfic to Python this.

不是特定于 Python 的。

The whole point of exceptions is to deal with the problem as close to where it was caused as possible.

异常的全部意义在于尽可能靠近引起问题的地方处理问题。

So you keep the code that could in exceptional cirumstances could trigger the problem and the resolution "next" to each other.

因此,您将可能在特殊情况下触发问题的代码与“相邻”的解决方案保持在一起。

The thing is you can't know all the exceptions that could be thrown by a piece of code. All you can know is that if it's a say a file not found exception, then you could trap it and to prompt the user to get one that does or cancel the function.

问题是你无法知道一段代码可能抛出的所有异常。您所能知道的是,如果是说未找到文件异常,那么您可以捕获它并提示用户获取执行或取消该功能的功能。

If you put try catch round that, then no matter what problem there was in your file routine (read only, permissions, UAC, not really a pdf, etc), every one will drop in to your file not found catch, and your user is screaming "but it is there, this code is crap"

如果你把 try catch 放在一边,那么无论你的文件例程中有什么问题(只读、权限、UAC,不是真正的 pdf 等),每个人都会进入你的文件 not found catch 和你的用户正在尖叫“但它就在那里,这段代码很垃圾”

Now there are a couple of situation where you might catch everything, but they should be chosen consciously.

现在有几种情况你可能会抓住一切,但应该有意识地选择它们。

They are catch, undo some local action (such as creating or locking a resource, (opening a file on disk to write for instance), then you throw the exception again, to be dealt with at a higher level)

它们是catch,撤消一些本地操作(例如创建或锁定资源,(例如打开磁盘上的文件进行写入),然后再次抛出异常,以在更高级别进行处理)

The other you is you don't care why it went wrong. Printing for instance. You might have a catch all round that, to say There is some problem with your printer, please sort it out, and not kill the application because of it. Ona similar vain if your code executed a series of separate tasks using some sort of schedule, you wouldnlt want the entire thing to die, because one of the tasks failed.

另一个你是你不在乎为什么会出错。以印刷为例。你可能有一个问题,说你的打印机有问题,请解决它,不要因为它而终止应用程序。如果您的代码使用某种时间表执行一系列单独的任务,那么类似的徒劳无功,您不会希望整个事情都死掉,因为其中一个任务失败了。

Note If you do the above, I can't recommend some sort of exception logging, e.g. try catch log end, highly enough.

注意如果您执行上述操作,我不能推荐某种异常日志记录,例如 try catch log end,足够高了。

回答by nipil

Here are the places where i use except without type

这是我使用的地方,除了没有类型

  1. quick and dirty prototyping
  1. 快速而肮脏的原型设计

That's the main use in my code for unchecked exceptions

这是我的代码中用于未经检查的异常的主要用途

  1. top level main() function, where i log every uncaught exception
  1. 顶级 main() 函数,我记录每个未捕获的异常

I always add this, so that production code does not spill stacktraces

我总是添加这个,这样生产代码就不会溢出堆栈跟踪

  1. between application layers
  1. 应用层之间

I have two ways to do it :

我有两种方法可以做到:

  • First way to do it : when a higher level layer calls a lower level function, it wrap the calls in typed excepts to handle the "top" lower level exceptions. But i add a generic except statement, to detect unhandled lower level exceptions in the lower level functions.
  • 第一种方法:当较高级别的层调用较低级别的函数时,它将调用包装在类型化的异常中以处理“顶级”较低级别的异常。但是我添加了一个通用的 except 语句,以检测低级函数中未处理的低级异常。

I prefer it this way, i find it easier to detect which exceptions should have been caught appropriately : i "see" the problem better when a lower level exception is logged by a higher level

我更喜欢这种方式,我发现更容易检测哪些异常应该被适当地捕获:当较低级别的异常被较高级别记录时,我会更好地“看到”问题

  • Second way to do it : each top level functions of lower level layers have their code wrapped in a generic except, to it catches all unhandled exception on that specific layer.
  • 第二种方法:较低层的每个顶层函数都将它们的代码包装在一个通用的 except 中,以便它捕获该特定层上的所有未处理的异常。

Some coworkers prefer this way, as it keeps lower level exceptions in lower level functions, where they "belong".

一些同事更喜欢这种方式,因为它在较低级别的功能中保留较低级别的异常,它们“属于”。

回答by Mekanic

Try this:

尝试这个:

try:
    #code
except ValueError:
    pass

I got the answer from this link, if anyone else run into this issue Check it out

我从这个链接得到了答案,如果其他人遇到这个问题,请查看