在 Python 中使用 try-except-else 是一个好习惯吗? [英] Is it a good practice to use try-except-else in Python?

查看:23
本文介绍了在 Python 中使用 try-except-else 是一个好习惯吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Python 中,我时不时地看到块:

From time to time in Python, I see the block:

try:
   try_this(whatever)
except SomeException as exception:
   #Handle exception
else:
   return something

try-except-else 存在的原因是什么?

我不喜欢那种编程,因为它使用异常来执行流控制.但是,如果它包含在语言中,那么它肯定有充分的理由,不是吗?

I do not like that kind of programming, as it is using exceptions to perform flow control. However, if it is included in the language, there must be a good reason for it, isn't it?

我的理解是异常不是错误,它们应该只用于异常情况(例如,我尝试将文件写入磁盘但没有更多空间,或者我可能没有权限),不用于流量控制.

It is my understanding that exceptions are not errors, and that they should only be used for exceptional conditions (e.g. I try to write a file into disk and there is no more space, or maybe I do not have permission), and not for flow control.

通常我将异常处理为:

something = some_default_value
try:
    something = try_this(whatever)
except SomeException as exception:
    #Handle exception
finally:
    return something

或者如果我真的不想在发生异常时返回任何东西,那么:

Or if I really do not want to return anything if an exception happens, then:

try:
    something = try_this(whatever)
    return something
except SomeException as exception:
    #Handle exception

推荐答案

我不知道是不是出于无知,但我不喜欢那样一种编程,因为它使用异常来执行流控制."

"I do not know if it is out of ignorance, but I do not like that kind of programming, as it is using exceptions to perform flow control."

在 Python 世界中,使用异常进行流量控制是常见且正常的.

In the Python world, using exceptions for flow control is common and normal.

即使是 Python 核心开发人员也使用异常进行流控制,并且这种风格已经深深融入语言中(即迭代器协议使用 StopIteration 表示循环终止.

Even the Python core developers use exceptions for flow-control and that style is heavily baked into the language (i.e. the iterator protocol uses StopIteration to signal loop termination).

此外,try-except-style 用于防止某些 "look-before-you-leap" 结构.例如,测试 os.path.exists 导致信息在您使用时可能已经过时.同样,Queue.full 返回可能过时的信息.try-except-else 风格 将在这些情况下生成更可靠的代码.

In addition, the try-except-style is used to prevent the race-conditions inherent in some of the "look-before-you-leap" constructs. For example, testing os.path.exists results in information that may be out-of-date by the time you use it. Likewise, Queue.full returns information that may be stale. The try-except-else style will produce more reliable code in these cases.

我的理解是异常不是错误,它们应该只是用于特殊情况"

"It my understanding that exceptions are not errors, they should only be used for exceptional conditions"

在其他一些语言中,该规则反映了其图书馆中反映的文化规范.规则"也部分基于这些语言的性能考虑.

In some other languages, that rule reflects their cultural norms as reflected in their libraries. The "rule" is also based in-part on performance considerations for those languages.

Python 文化规范有些不同.在许多情况下,您必须为控制流使用异常.此外,在 Python 中使用异常不会像在某些编译语言中那样减慢周围代码和调用代码的速度(即 CPython 已经实现了每一步的异常检查代码,不管你是否真的使用异常).

The Python cultural norm is somewhat different. In many cases, you must use exceptions for control-flow. Also, the use of exceptions in Python does not slow the surrounding code and calling code as it does in some compiled languages (i.e. CPython already implements code for exception checking at every step, regardless of whether you actually use exceptions or not).

换句话说,您对例外是为了例外"的理解在其他一些语言中是有意义的,但对 Python 来说则不然.

In other words, your understanding that "exceptions are for the exceptional" is a rule that makes sense in some other languages, but not for Python.

"但是,如果它包含在语言本身中,则必须有一个很好的理由,不是吗?"

"However, if it is included in the language itself, there must be a good reason for it, isn't it?"

除了有助于避免竞争条件外,异常对于将错误处理拉到循环外也非常有用.这是解释性语言的必要优化,这些语言往往没有自动循环不变代码运动.

Besides helping to avoid race-conditions, exceptions are also very useful for pulling error-handling outside loops. This is a necessary optimization in interpreted languages which do not tend to have automatic loop invariant code motion.

此外,在处理问题的能力与问题出现的地方相去甚远的常见情况下,异常可以大大简化代码.例如,通常有顶级用户界面代码调用业务逻辑的代码,而业务逻辑又调用低级例程.低级例程中出现的情况(例如数据库访问中唯一键的重复记录)只能在顶级代码中处理(例如向用户询问与现有键不冲突的新键).对这种控制流使用异常允许中级例程完全忽略这个问题,并与流控制的那个方面很好地分离.

Also, exceptions can simplify code quite a bit in common situations where the ability to handle an issue is far removed from where the issue arose. For example, it is common to have top level user-interface code calling code for business logic which in turn calls low-level routines. Situations arising in the low-level routines (such as duplicate records for unique keys in database accesses) can only be handled in top-level code (such as asking the user for a new key that doesn't conflict with existing keys). The use of exceptions for this kind of control-flow allows the mid-level routines to completely ignore the issue and be nicely decoupled from that aspect of flow-control.

有一个不错的博客在这里发表关于例外的必要性.

此外,请参阅此 Stack Overflow 答案:异常真的是异常错误吗?

Also, see this Stack Overflow answer: Are exceptions really for exceptional errors?

try-except-else 存在的原因是什么?"

"What is the reason for the try-except-else to exist?"

else 子句本身很有趣.它在没有异常时但在 finally 子句之前运行.这是它的主要目的.

The else-clause itself is interesting. It runs when there is no exception but before the finally-clause. That is its primary purpose.

如果没有 else 子句,在完成之前运行附加代码的唯一选择就是将代码添加到 try 子句中的笨拙做法.这很笨拙,因为它有风险在不受 try 块保护的代码中引发异常.

Without the else-clause, the only option to run additional code before finalization would be the clumsy practice of adding the code to the try-clause. That is clumsy because it risks raising exceptions in code that wasn't intended to be protected by the try-block.

在最终确定之前运行其他不受保护的代码的用例并不经常出现.因此,不要期望在已发布的代码中看到很多示例.有点罕见.

The use-case of running additional unprotected code prior to finalization doesn't arise very often. So, don't expect to see many examples in published code. It is somewhat rare.

else 子句的另一个用例是执行在没有异常发生时必须发生的动作,以及在处理异常时不会发生的动作.例如:

Another use-case for the else-clause is to perform actions that must occur when no exception occurs and that do not occur when exceptions are handled. For example:

recip = float('Inf')
try:
    recip = 1 / f(x)
except ZeroDivisionError:
    logging.info('Infinite result')
else:
    logging.info('Finite result')

另一个例子发生在 unittest runners 中:

Another example occurs in unittest runners:

try:
    tests_run += 1
    run_testcase(case)
except Exception:
    tests_failed += 1
    logging.exception('Failing test case: %r', case)
    print('F', end='')
else:
    logging.info('Successful test case: %r', case)
    print('.', end='')

最后,在 try 块中 else 子句的最常见用途是进行一些美化(将异常结果和非异常结果对齐在同一缩进级别).这种用法始终是可选的,并不是绝对必要的.

Lastly, the most common use of an else-clause in a try-block is for a bit of beautification (aligning the exceptional outcomes and non-exceptional outcomes at the same level of indentation). This use is always optional and isn't strictly necessary.

这篇关于在 Python 中使用 try-except-else 是一个好习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆