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

时间:2015-05-22 01:50:26

标签: python exception exception-handling

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

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="rad[timeout > 30]">
    <xsl:copy>
        <timeout>100</timeout>
    </xsl:copy>
    <warnings>
        <warning>Time out of RAD changed.</warning>
    </warnings>
</xsl:template>

</xsl:stylesheet>

我目前有这个代码来处理一个新的令牌,如果它到期,但问题是,如果有一个异常,它会跳过它需要做的动作。我知道我可以把try块里面的内容添加到try: if uploadedContent is not None: thing.action(uploadedContent) except LoginOrScopeRequired: print("Logging in...") set_access_credentials({"identity", "submit"}, get_access_token()) 块的末尾,但它有更优雅的方法吗?

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

2 个答案:

答案 0 :(得分:3)

某些语言(如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 = True行。

修改

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

答案 1 :(得分:3)

使用函数装饰器/包装器来执行此操作被认为是惯用的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 Decorators

更新还有一个很好的库,可以通过更多功能实现此功能:retrying以及其他一些相关/类似问题How to retry after exception in python?和{{ 3}}

更新#2:我已经对装饰师进行了一些评论,所以希望您能够了解过程中每个步骤的进展情况。不可否认,装饰师一开始并不容易理解,所以我建议你阅读Pythonic way of retry running a function