Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否可以在不考虑异常的情况下重试特定代码段?_Python_Decorator_Contextmanager - Fatal编程技术网

Python 是否可以在不考虑异常的情况下重试特定代码段?

Python 是否可以在不考虑异常的情况下重试特定代码段?,python,decorator,contextmanager,Python,Decorator,Contextmanager,在我的Python项目中,有很多代码如下所示: # the codes I with to simplify for _ in range(3): try: # do something break except: print "Exception. Retrying..." continue else: print "ERROR!" 我知道我可以使用contextmanager简化“尝试…除了…”部分,

在我的Python项目中,有很多代码如下所示:

# the codes I with to simplify
for _ in range(3):
    try:
        # do something
        break
    except:
        print "Exception. Retrying..."
        continue
 else:
    print "ERROR!"
我知道我可以使用contextmanager简化“尝试…除了…”部分,方法如下:

# define the exception handler function first
@contextmanager
def ignore_exception():
    try:
        yield
    except:
        print "Exception. Retrying..."
        continue

# then use "with" to simplify the codes
with ignore_exception:
    # do something
但是,我不能以相同的方式添加“for”循环,即

# define the exception handler function with for loop first
@contextmanager
def ignore_exception():
    try:
        for _ in range(3):
            yield
            break
        else:
            print "ERROR!"
    except:
        print "Exception. Retrying..."
        continue

# then use "with" to simplify the codes
with ignore_exception:
    # do something
将引发一个异常:

/usr/lib/python2.7/contextlib.pyc in __exit__(self, type, value, traceback)
     26                 return
     27             else:
---> 28                 raise RuntimeError("generator didn't stop")
     29         else:
     30             if value is None:

RuntimeError: generator didn't stop
有没有办法克服这种错误并将我的代码简化为:

# ideal codes
with xxxxxx: # don't have to use "with" statement
    # do something

只需编写一个decorator,它可以处理循环和异常忽略部分,如下所示

def trys(maximum_tries=3):
    def decorator(func):
        def inner(*args, **kwargs):
            for _ in range(1, maximum_tries + 1):
                try:
                    return func(*args, **kwargs)
                except ArithmeticError, e:
                    print("Error : [{}], Retrying Attempt {}...".format(e, _))
                else:
                    break
        return inner
    return decorator
outer_a = 0


@trys(maximum_tries=4)
def adder(a):
    global outer_a
    outer_a += 1
    if outer_a < 4:
        raise ArithmeticError("Cannot add with {}".format(outer_a))
    else:
        return a + outer_a

print(adder(0))
现在,您可以这样调用它

def trys(maximum_tries=3):
    def decorator(func):
        def inner(*args, **kwargs):
            for _ in range(1, maximum_tries + 1):
                try:
                    return func(*args, **kwargs)
                except ArithmeticError, e:
                    print("Error : [{}], Retrying Attempt {}...".format(e, _))
                else:
                    break
        return inner
    return decorator
outer_a = 0


@trys(maximum_tries=4)
def adder(a):
    global outer_a
    outer_a += 1
    if outer_a < 4:
        raise ArithmeticError("Cannot add with {}".format(outer_a))
    else:
        return a + outer_a

print(adder(0))

注意:有一个名为的开源库,它以更好、更灵活的方式完成相同的任务。如果可能,您可能希望检查并使用它,而不是滚动您自己的装饰程序。不要重复你自己:-)

这意味着我必须将所有内容都放在函数中才能使用装饰器。有没有一种方法可以避免像宏在C/C++中所能做的那样使用函数。例如,我只想重试第n到n+10行3次,然后重试第n+11到n+20行2次。为什么contextmanager不允许在内部使用循环?