如果抛出异常,如何再次调用 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
的理解还不够深入,不知道它是否能解决我的问题。那么将它附加到最后是最好的解决方案还是有更好的方法?
某些语言,如 ruby
允许您在异常捕获块中放置一个 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 次重试后退出。
用函数 decorator/wrapper:
来做这件事被认为是惯用的 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 as well as several other related/similar questions How to retry after exception in python? and Pythonic way of retry running a function
更新 #2: 我对装饰器做了一些评论,希望您能理解该过程的每个步骤中发生了什么。诚然,装饰器一开始并不那么容易理解,所以我建议您阅读 Understanding Python Decorators in 12 easy step
我是 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
的理解还不够深入,不知道它是否能解决我的问题。那么将它附加到最后是最好的解决方案还是有更好的方法?
某些语言,如 ruby
允许您在异常捕获块中放置一个 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 次重试后退出。
用函数 decorator/wrapper:
来做这件事被认为是惯用的 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 as well as several other related/similar questions How to retry after exception in python? and Pythonic way of retry running a function
更新 #2: 我对装饰器做了一些评论,希望您能理解该过程的每个步骤中发生了什么。诚然,装饰器一开始并不那么容易理解,所以我建议您阅读 Understanding Python Decorators in 12 easy step