繁体   English   中英

如果抛出异常,如何再次调用try块中的代码?

[英]How to call code inside try block one more time if exception is thrown?

我是python的新手,我正在编写使用OAuth进行身份验证的代码,当令牌在60分钟后过期时,它需要获得一个新的。

try:
    if uploadedContent is not None:
       thing.action(uploadedContent)

except LoginOrScopeRequired:
    print("Logging in...")
    set_access_credentials({"identity", "submit"}, get_access_token())

我目前有这个代码来处理一个新的令牌,如果它到期,但问题是,如果有一个异常,它跳过它需要做的动作。 我明白我可以把try块里面的内容添加到except块的末尾,但它有更优雅的方法吗?

我的一些研究,导致了with声明,但我不明白with不够好,知道这是否能解决我的问题。 那么将它追加到最后的最佳解决方案还是有更好的东西?

使用函数装饰器/包装器来执行此操作被认为是惯用的Python:

例:

#!/usr/bin/env python


from functools import wraps


def retry_on_error(ntries=1):
    """
    A decorator that returns a wrapper function that calls
    the wrapped function repeatedly up to ntries if an
    exception is encountered.
    """

    def decorator(f):  # wrapping the original function
        @wraps(f)  # make the wrapped function look like the original
        def wrapper(*args, **kwargs):  # our function wrapped that calls the original
            for i in xrange(ntries):
                try:
                    return f(*args, **kwargs)
                except Exception as e:
                    print("Error executing {0:s} retrying {1:d}/{2:d}".format(f.__name__, i, ntries))
                    print("Error was {0:s}".format(e))

        return wrapper

    return decorator  # returning the new wrapped function


@retry_on_error()
def f():
    n = getattr(f, "n", 0)
    try:
        if not n:
            raise ValueError("n < 0")
    finally:
        setattr(f, "n", n + 1)

输出:

$ python -i foo.py
>>> f()
Error executing f retrying 0/1
Error was n < 0
>>> f()
>>> 

请参阅: Python装饰器以获取其他示例。

更新:还有一个很好的库,它实现了这个功能以及一些其他功能: 重试以及其他一些相关/类似的问题如何在python中的异常后重试? Pythonic重试方式运行一个函数

更新#2:我对装饰器进行了一些评论,所以希望你能够理解这个过程的每一步都在发生什么。 不可否认,装饰器起初并不容易理解,因此我建议您阅读12个简单步骤中的了解Python装饰器

ruby这样的某些语言允许你在异常catch块中放置一个retry语句,这使得这非常简单。 不幸的是,在Python中你需要将它包装在while语句中:

success = False
while not success
    try:
        if uploadedContent is not None:
           thing.action(uploadedContent)
        success = True
    except LoginOrScopeRequired:
        print("Logging in...")
        set_access_credentials({"identity", "submit"}, get_access_token())

请注意,只有在没有异常发生时才会达到success = Truesuccess = True

编辑

您还需要跟踪计数器中的attempts ,以确保它不会永远循环并在3次重试后退出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM