Python中的简明异常处理

时间:2014-07-14 01:00:49

标签: python exception-handling

我喜欢避免“在你跳跃之前”的范例,因为我重视易于阅读的代码。在某些情况下,我无法预测是否会发生错误,例如资源可用性或内存不足错误。我还没有找到一种干净的方式来编写重复或冗长的代码来处理这些场景。

以下示例略有可读性,但重复的代码是不可接受的。

try:
    myobject.write(filename)
except OSError:
    if prompt("%s is in use by another application." +
              "Close that application and try again.") == "Try again":
        myobject.write(filename) #repeated code

为了删除重复的代码,我必须添加更多行并缩进所有内容,从而降低可读性。

success = False
while not success:
    try:
        myobject.write(filename)
        success = True
    except OSError:
        if prompt("%s is in use by another application." +
                  "Close that application and try again.") != "Try again":
            break

是否有一种较短的方式在Python中编写不会重复代码的方法?

3 个答案:

答案 0 :(得分:6)

除了切换到while True之外,您还可以添加retry装饰器,并将您的可重试代码移至由retry修饰的函数:

from functools import wraps
from functools import update_wrapper


def retry(prompt_text="An error occured! Retry (y/n)?", 
          prompt_match='y',
          exception=Exception):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            while True:
                try:
                    ret = func(*args, **kwargs)
                    break
                except exception:
                    if raw_input(prompt_text) == prompt_match:
                        ret = None
                        break
            return ret 
        return update_wrapper(wrapper, func)
    return decorator

@retry(prompt_text="your prompt: ", prompt_match="quit", exception=OSError)
def do_write(myobject, filename):
    myobject.write(filename)

if __name__ == "__main__":
    myobject = ...
    filename = ...
    do_write(myobject, filename) # This will be retried.

如果您在多个地方使用此模式,可能只值得努力。

答案 1 :(得分:2)

  

是否有一种较短的用Python编写的方法   重复的代码?

不是真的。您可以使用while True:循环并删除success变量:

while True:
    try:
        myobject.write(filename)
        break
    except OSError:
        if prompt("%s is in use by another application."
                  "Close that application and try again.") != "Try again":
            break

但是,这仍然保持可读性,同样紧凑。

另外,您会注意到我删除了if语句行的+。没有必要,因为相邻的字符串文字是自动连接的。

答案 2 :(得分:1)

您可以使用接受参数作为输入的装饰器类来包装函数,以概括异常处理:

class exception_handler(object):

    def __init__(self, prompt_text, prompt_match, exception):
        self.prompt = prompt_text
        self.match = prompt_match
        self.exception = exception

    def __call__(self, f):
        def wrapped_f(*args, **kwargs):
            while True:
                try:
                    f(*args, **kwargs)
                    break
                except self.exception:
                    if raw_input(self.prompt) == self.match:
                        break       
        return wrapped_f


@exception_handler("your prompt (type 'quit' to exit): ", "quit", OSError)
def f(filename):
    print("before writing to file: {}".format(filename))
    # myobject.write(filename)
    raise OSError("testing...")