Python中异常处理的首选风格

3

这是一个关于最佳实践的一般性问题。以下哪个try-except示例更好(该函数本身是一个简单的requests.get()包装器):

def get(self, url, params=params):
    try:
        response = {}
        response = requests.get(url, params=params)
    except requests.ConnectionError,e:
        log.exception(e)
    finally:
        return response

或者

def get(self, url, params=params):
    try:
        return requests.get(url, params=params)
    except requests.ConnectionError,e:
        log.exception(e)
        return {}

或许两者都不太理想?我似乎经常为错误日志编写这种包装函数,想知道最具Python风格的方式是什么。如果有任何建议,将不胜感激。


2
推荐使用except requests.ConnectionError as e的写法,而不是使用逗号。这是因为我们还会使用逗号来捕获多个异常。 - Benjamin Hodgson
@poorsod 在哪里写的?(我很想读一下。) - akaRem
2
@akaRem:这是Python3的语法,并已向后移植到Python2.6。有关更多信息,请参见PEP(http://www.python.org/dev/peps/pep-3110/)。因此,它并不像poorsod所描述的那样“建议”,而是为了实现py3k兼容性而非常有用。 - SilentGhost
1
@SilentGhost 我假设 OP 正在使用 Python 的最新版本。在 Python 2 的最新版本中,逗号已被弃用,取而代之的是 'as',而在 Python 3 中则完全消失了。 - Benjamin Hodgson
@SilentGhost,如何接受多个异常作为[many]名称?是except E1,E2 as N还是except E1,E2 as N1,N2或其他方式? - akaRem
@akaRem:在任何给定时间只能传播一个异常。因此,我认为您无法区分不同的异常,而且我也看不出有什么可能的用例。 - SilentGhost
4个回答

5

在异常情况下最好不要返回任何内容,我同意Mark的观点-在异常情况下没有必要返回任何内容。

def get(self, url, params=params):
    try:
        return requests.get(url, params=params)
    except requests.ConnectionError,e:
        log.exception(e)

res = get(...)
if res is not None:
    #Proccess with data

#or
if res is None:
    #aborting

2
第二个版本看起来还不错,但第一个版本有点问题。例如,如果try-except中的代码引发除ConnectionError以外的任何异常,由于从finally返回会抑制任何异常,因此您仍将返回{}。后一种特性相当令人困惑(在回答之前我不得不自己尝试一下)。
您也可以使用try的else子句:
def get(self, url, params=params):
    try:
        # Do dangerous some stuff here
    except requests.ConnectionError,e:
        # handle the exception

    else:  # If nothing happened
        # Do some safe stuff here
        return some_result
    finally:
        # Do some mandatory stuff

这可以更精确地定义异常范围。

1

对我来说,第二个版本更清晰。

第一个版本有点令人困惑。一开始我以为您是在两次分配相同的变量,这是一个错误。只有经过一些思考,我才明白为什么这样可以运行。


0
我可能会考虑编写一个上下文管理器。
from contextlib import contextmanager

@contextmanager
def get(url, params=params):
    try:
        yield requests.get(url, params=params)       
    except requests.ConnectionError as e:
        log.exception(e)
        yield {}
    except:
        raise # anything else stays an exception

然后:

with get(...) as res:
    print res # will be actual response or empty dict

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