用python语言结合“for”和“try”块

时间:2022-02-02 22:42:01

I have code where I am parsing a JSON feed.

我有解析JSON提要的代码。

For each array I have code that looks like:

对于每个数组,我都有如下代码:

for node in parse_me:
    # It's important that one iteration failing doesn't cause all iterations to fail.
    try:
        i = node['id'] # KeyError?
        function_that_needs_int (i) # TypeError?
        # possibly other stuff

    except Exception as e:
        LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node))

I do not like that this makes my for loops double-nested just because I need to stop exceptions from aborting the loop. Is there a way to flatten this code?

我不喜欢这样做,因为我需要阻止异常中止循环。有没有办法使这段代码变平?

2 个解决方案

#1


5  

Then you should do things like

那么你应该做一些类似的事情

def iterate_safe(parse_me, message, action):
    for node in parse_me:
        try:
            action(node)
        except Exception as e:
            LogErrorMessage(message.fmt(e, node))

and then call it like

然后这样称呼它

def action(node):
    do_whatever_must_be_done_with(node)

iterate_safe(parse_me, action, 'blah blah blah {} in node {}')
iterate_safe(parse_me, other_action, 'spam ham {} in node {}')

#2


1  

EDIT: The original question seemed to imply that the entire parse operation was in one giant for-loop; my answer has been modified to reflect comments below.

编辑:最初的问题似乎暗示了整个解析操作是一个巨大的for循环;我的回答被修改以反映下面的评论。

Instead of writing multiple for-loops, each of which must include a try/catch block, write functions describing what must be done within the loops, and write a decorator to apply to them that will surround each one with the for-loop and the try/catch logging logic. This is a bit like glglgl's solution, but a bit more Pythonic (in my opinion). For example:

不是编写多个for循环,每个for循环必须包含一个try/catch块,而是编写描述循环中必须完成的操作的函数,并编写一个decorator来应用它们,它将用for循环和try/catch日志记录逻辑包围每个for循环。这有点像glglgl的解决方案,但更像毕达哥拉斯(在我看来)。例如:

def apply_to_nodes_and_log_errs(node_visit_func):
    def safe_iterating_visitor(nodes_to_parse):
        for node in nodes_to_parse:
            try:
                node_visit_func(node)
            except StandardError as e:
                LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node))
    return safe_iterating_visitor

@apply_to_nodes_and_log_errs
def action_one(node):
    # ... "lots of stuff" :D

@apply_to_nodes_and_log_errs
def action_two(node):
    # different stuff

If you'd rather break the decorator into chunks:

如果你愿意把装饰者分成几块:

def iterate_over_nodelist(node_visit_func):
    def iterating_visitor(nodes_to_parse):
        for node in nodes_to_parse:
            node_visit_func(node)
    return iterating_visitor

def safely_visit_log_errs(node_visit_func):
    def safe_logging_visitor(node_to_visit):
        try:
            node_visit_func(node)
        except StandardError as e:
            LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node))
    return safe_logging_visitor

def apply_to_nodes_and_log_errs(node_visit_func):
    return iterate_over_nodelist(safely_visit_log_errs(node_visit_func))

# ... write visit functions

This could be further improved using functools.wraps.

这可以通过使用功能工具进行进一步的改进。

Note that although this may look a little ugly if your standard is "use as few levels of indentation as possible," it's actually quite Pythonic; there's really no way to avoid quite a few indentation levels when writing decorators.

请注意,如果您的标准是“尽可能少地使用缩进”,这可能看起来有点难看,但实际上它是非常python化的;在编写decorator时,确实无法避免相当多的缩进级别。

Finally, note that change from Exception to StandardError, which I still strongly recommend.

最后,请注意从异常到标准镜的更改,我仍然强烈建议这样做。

#1


5  

Then you should do things like

那么你应该做一些类似的事情

def iterate_safe(parse_me, message, action):
    for node in parse_me:
        try:
            action(node)
        except Exception as e:
            LogErrorMessage(message.fmt(e, node))

and then call it like

然后这样称呼它

def action(node):
    do_whatever_must_be_done_with(node)

iterate_safe(parse_me, action, 'blah blah blah {} in node {}')
iterate_safe(parse_me, other_action, 'spam ham {} in node {}')

#2


1  

EDIT: The original question seemed to imply that the entire parse operation was in one giant for-loop; my answer has been modified to reflect comments below.

编辑:最初的问题似乎暗示了整个解析操作是一个巨大的for循环;我的回答被修改以反映下面的评论。

Instead of writing multiple for-loops, each of which must include a try/catch block, write functions describing what must be done within the loops, and write a decorator to apply to them that will surround each one with the for-loop and the try/catch logging logic. This is a bit like glglgl's solution, but a bit more Pythonic (in my opinion). For example:

不是编写多个for循环,每个for循环必须包含一个try/catch块,而是编写描述循环中必须完成的操作的函数,并编写一个decorator来应用它们,它将用for循环和try/catch日志记录逻辑包围每个for循环。这有点像glglgl的解决方案,但更像毕达哥拉斯(在我看来)。例如:

def apply_to_nodes_and_log_errs(node_visit_func):
    def safe_iterating_visitor(nodes_to_parse):
        for node in nodes_to_parse:
            try:
                node_visit_func(node)
            except StandardError as e:
                LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node))
    return safe_iterating_visitor

@apply_to_nodes_and_log_errs
def action_one(node):
    # ... "lots of stuff" :D

@apply_to_nodes_and_log_errs
def action_two(node):
    # different stuff

If you'd rather break the decorator into chunks:

如果你愿意把装饰者分成几块:

def iterate_over_nodelist(node_visit_func):
    def iterating_visitor(nodes_to_parse):
        for node in nodes_to_parse:
            node_visit_func(node)
    return iterating_visitor

def safely_visit_log_errs(node_visit_func):
    def safe_logging_visitor(node_to_visit):
        try:
            node_visit_func(node)
        except StandardError as e:
            LogErrorMessage ('blah blah blah {} in node {}'.fmt(e, node))
    return safe_logging_visitor

def apply_to_nodes_and_log_errs(node_visit_func):
    return iterate_over_nodelist(safely_visit_log_errs(node_visit_func))

# ... write visit functions

This could be further improved using functools.wraps.

这可以通过使用功能工具进行进一步的改进。

Note that although this may look a little ugly if your standard is "use as few levels of indentation as possible," it's actually quite Pythonic; there's really no way to avoid quite a few indentation levels when writing decorators.

请注意,如果您的标准是“尽可能少地使用缩进”,这可能看起来有点难看,但实际上它是非常python化的;在编写decorator时,确实无法避免相当多的缩进级别。

Finally, note that change from Exception to StandardError, which I still strongly recommend.

最后,请注意从异常到标准镜的更改,我仍然强烈建议这样做。