Python try-except块的DRY方法?

Mic*_*ter 3 python python-2.7 try-except

目标:我有几行代码,每行都能产生相同类型的错误,并保证同样的响应.如何使用try-except块防止"不要重复"问题.

背景:

我使用ReGex从文本文件中抓取格式不佳的数据,并将其输入到自定义对象的字段中.代码工作得很好,除非字段留空,在这种情况下它会抛出错误.

我在try-except块中处理此错误.如果出错,请在对象的字段中插入一个空白(即'').

问题是它变得易于阅读,很好,Python代码变成了一堆乱七八糟的块,每个块都做同样的事情.这是一个'不要重复自己'(又名DRY)违规行为.

代码:

之前:

sample.thickness = find_field('Thickness', sample_datum)[0]
sample.max_tension = find_field('Maximum Load', sample_datum)[0]
sample.max_length = find_field('Maximum Extension', sample_datum)[0]
sample.test_type = sample_test
Run Code Online (Sandbox Code Playgroud)

后:

try:
    sample.thickness = find_field('Thickness', sample_datum)[0]
except:
    sample.thickness = ''

try:
    sample.max_tension = find_field('Maximum Load', sample_datum)[0]
except:
    sample.max_tension = ''

try:
    sample.max_length = find_field('Maximum Extension', sample_datum)[0]
except: 
    sample.max_length = ''

try:    
    sample.test_type = sample_test
except:
    sample.test_type = ''
Run Code Online (Sandbox Code Playgroud)

我需要的:

是否有一些Pythonic方式来写这个?如果在任何这些行上存在索引超出范围的错误(表示该字段为空,并且ReGex未能返回任何内容),我可以说一些块,在示例字段中插入一个空白.

Mat*_*ela 6

如何重构一个函数呢?

def maybe_find_field(name, datum):
    try:
        return find_field(name, datum)[0]
    except IndexError: # Example of specific exception to catch
        return ''

sample.thickness = maybe_find_field('Thickness', sample_datum)
sample.max_tension = maybe_find_field('Maximum Load', sample_datum)
sample.max_length = maybe_find_field('Maximum Extension', sample_datum)
sample.test_type = sample_test
Run Code Online (Sandbox Code Playgroud)

顺便说一句,不要只是捕捉所有可能的例外,except:除非那是你想要做的.捕获所有内容可能会隐藏一些实现错误,以后很难调试.只要你可以,就可以将你的except案例绑定到你需要的特定异常.


Chr*_*ris 5

不太符合问题,但谷歌把我送到这里,所以其他人可能会来。

我在两个单独的 Django 视图中有post函数,它们调用类似的后端函数并需要相同的异常处理。

我通过提取整个except:树并将其粘贴到装饰器中解决了这个问题。

前:

# twice this
def post(request):
    try:
        return backend_function(request.post)
    except ProblemA as e:
        return Response("Problem A has occurred, try this to fix it.", status=400)
    except ProblemB as e:
        return Response("Problem B has occurred, try this to fix it.", status=400)
    except ProblemC as e:
        return Response("Problem C has occurred, try this to fix it.", status=400)
    except ProblemD as e:
        return Response("Problem D has occurred, try this to fix it.", status=400)
Run Code Online (Sandbox Code Playgroud)

后:

# once this
def catch_all_those_pesky_exceptions(original_function):
    def decorated(*args, **kwargs):
        try:
            return original_function(*args, **kwargs)
        except ProblemA as e:
            return Response("Problem A has occurred, try this to fix it.", status=400)
        except ProblemB as e:
            return Response("Problem B has occurred, try this to fix it.", status=400)
        except ProblemC as e:
            return Response("Problem C has occurred, try this to fix it.", status=400)
        except ProblemD as e:
            return Response("Problem D has occurred, try this to fix it.", status=400)

    return decorated

# twice this - note the @decorator matching the above function.
@catch_all_those_pesky_exceptions
def post(request):
    return backend_function(request.post)
Run Code Online (Sandbox Code Playgroud)

现在我可以在一个地方添加更多异常处理。