<p>一般来说,您应该“捕获”您希望发生的异常(因为它们可能是由用户错误或程序控制范围之外的其他环境问题引起的),特别是如果您知道代码可以对它们做些什么的话。仅仅在错误报告中提供更多细节是一个无关紧要的问题,尽管有些程序的规范可能需要这样做(例如,一个长时间运行的服务器不应该因为这样的问题而崩溃,而是记录大量的状态信息,给用户一个摘要解释,并为将来的查询继续工作)。</p>
<p><code>NameError</code>,<code>TypeError</code>,<code>KeyError</code>,<code>ValueError</code>,<code>SyntaxError</code>,<code>AttributeError</code>等等,都可以认为是由于程序中的错误——错误,而不是程序员控制之外的问题。如果您正在发布库或框架,以便您的代码将被您控制之外的其他代码调用,那么此类错误很可能出现在其他代码中;您通常应该让异常传播以帮助其他程序员调试他们自己的错误。如果你要发布一个应用程序,你就拥有这些bug,你必须选择帮助你找到它们的策略。</p>
<p>如果最终用户运行程序时出现错误,则应记录大量状态信息,并向用户提供简要解释和道歉(如果无法自动执行,则可能请求向您发送日志信息,或者至少在将用户计算机中的任何内容发送到您的计算机之前请求权限)。到目前为止,您可能能够保存用户的一些工作,但通常(在已知有bug的程序中)这些工作可能无论如何都不起作用。</p>
<p>当然,大多数bug都应该在您自己的测试过程中出现;在这种情况下,传播异常非常有用,因为您可以将其连接到调试器并探索bug的详细信息。</p>
<p>有时,像这样的异常出现仅仅是因为“请求宽恕比请求许可更容易”(EAFP)——这是Python中一种完全可以接受的编程技术。在那种情况下,你当然应该马上处理。例如:</p>
<pre><code>try:
return mylist[theindex]
except IndexError:
return None
</code></pre>
<p>在这里,您可能希望<code>theindex</code>通常是进入<code>mylist</code>的有效索引,但有时会超出<code>mylist</code>的界限——根据此片段所属的假设应用程序的语义,后一种情况不是错误,考虑到列表在概念上用无限个<code>None</code>s在两边扩展,只需修复一点异常。尝试/排除比正确检查索引的正值和负值更容易(如果超出界限的情况确实很少发生,则速度更快)。</p>
<p>由于dicts的<code>getattr</code>内置和<code>get</code>方法(允许您提供默认值)、<code>collections.defaultdict</code>等,类似地,<code>KeyError</code>和<code>AttributeError</code>的适当情况发生的频率也较低,但是列表没有这些的直接等价项,因此try/except更常见于<code>IndexError</code>。</p>
<p>尝试捕捉语法错误、类型错误、值错误、名称错误等是比较少见和有争议的——尽管如果在“插件”中诊断出错误肯定是合适的,您的框架/应用程序试图动态加载和执行的超出您控制范围的第三方代码(实际上,在这种情况下,您正在提供库等,并且需要与超出您控制范围的代码和平共存,这很可能是错误的)。类型和值错误有时可能发生在EAFP模式中——例如,当您试图重载一个函数以接受字符串或数字,并且在每种情况下的行为略有不同时,捕获此类错误可能比尝试检查类型要好——但这样重载的函数的概念往往并不十分可疑。</p>
<p>回到“用户和环境错误”,用户在给您输入时,不可避免地会犯错误,指出一个实际上不在附近的文件名(或者您没有读取或写入的权限,如果这是您的等等:当然,所有这些错误都应该被捕捉到,并向用户清楚地解释出了什么问题,还有一个让输入正确的机会。网络有时会出现故障,数据库或其他外部服务器可能无法按预期做出响应,等等——有时值得抓住这些问题并重试(可能在稍等之后——可能向用户指出问题所在,e、 g.他们可能不小心拔下了电缆,你想给他们一个机会,让他们修复问题,告诉你什么时候再试一次),有时(特别是在无人值守的长时间运行的程序中),除了命令关机(以及详细记录环境的每一个可能相关方面)之外,你无能为力。</p>
<p>所以,简言之,你的问题的答案是,“这取决于”;—)。我希望我在列出它所依赖的许多情况和方面,并建议对这些问题采取什么样的普遍最有用的态度时,我是有用的。</p>