我喜欢避免“在你跳跃之前”的范例,因为我重视易于阅读的代码。在某些情况下,我无法预测是否会发生错误,例如资源可用性或内存不足错误。我还没有找到一种干净的方式来编写重复或冗长的代码来处理这些场景。
以下示例略有可读性,但重复的代码是不可接受的。
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中编写不会重复代码的方法?
答案 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...")