记住为以后处理它们而引发的异常

时间:2017-07-25 09:58:18

标签: python exception logging exception-handling

TLDR:我想让一个函数运行某些异常,最后显示它们并使函数引发异常。

我正在构建一个函数(见下文),通过创建表格" value":" path"来获取字典中每个值的路径。我有一个递归子函数遍历字典在每个节点上进行处理,当一个节点不支持类型时抛出一个TypeError,当一个值已经存在时抛出一个KeyError。

我想做的是对整个字典进行处理,忽略这些异常并最终处理它们,这样我就可以给出每个有问题的值的路径。如果没有引发异常,我想保存扁平字典。

如果我在try中包装对flatten_dict的调用...除了块之外,只会引发第一个异常,这会使所有有问题的值变得乏味。我考虑过使用日志记录,但后来我不知道如何让函数在结尾处引发异常,以便我可以采取相应的行动。

我想知道是否有办法做到这一点,或者如果它是一个标志我应该改变我的设计?

由于

def flatten_dict(dictionary):
    """
    Flattens a dictionary to get the path to each value in the dict in dpath format (https://pypi.python.org/pypi/dpath/)
    Returns a dict of the form "value":"path"

    param: dictionary: the dictionary to be flattened, should contain each value only once, and all values should be strings

    >>> reverse_flatten_dict({"k1":{"k2":"v2", "k3":["v3","v4"]}})
    {"v2":"k1/k2","v3":"k1/k3/0","v4":"k1/k3/1"}
    """

    def recursive_call(value, path, flattened):
        """
        Recursively traverse the dictionary to add the path to each string \
        value it encounters to the flattened dict
        """
        if isinstance(value, dict):
            for key, val in value.items():
                new_path = "{}/{}".format(path,key)
                recursive_call(val, new_path, flattened)
        elif isinstance(value, list):
            for i, val in enumerate(value):
                new_path = "{}/{}".format(path,i)
                recursive_call(val, new_path, flattened)
        elif isinstance(value, basestring):
            if value in flattened:
                raise KeyError("flatten_dict: The value at {} is present more \
                than once in the dictionary".format(path))
            flattened[value] = path
        else:
            raise TypeError("flatten_dict: Value of invalid type at {},\
            value ignored. Should be dict, list or basestring".format(path))

    path = ""
    flattened = {}
    if dictionary:
        recursive_call(dictionary, path, flattened)

    return flattened

1 个答案:

答案 0 :(得分:1)

可能有更好的方法,但最简单的方法是使用最少的代码调整来创建一个空列表,在if dictionary:之上创建一个空列表,将它传递给递归函数,然后向它附加任何消息。然后在最后检查是否有任何并将它们作为一个例外。

示例代码:(注意:我使用的是Python 3,所以我无法测试这些确切的代码。我添加的所有部分工作,其余部分从你的帖子,所以它也应该有用。)

def flatten_dict(dictionary):
    """
    Flattens a dictionary to get the path to each value in the dict in dpath format (https://pypi.python.org/pypi/dpath/)
    Returns a dict of the form "value":"path"

    param: dictionary: the dictionary to be flattened, should contain each value only once, and all values should be strings

    >>> reverse_flatten_dict({"k1":{"k2":"v2", "k3":["v3","v4"]}})
    {"v2":"k1/k2","v3":"k1/k3/0","v4":"k1/k3/1"}
    """

    def recursive_call(value, path, flattened, error_list):
        """
        Recursively traverse the dictionary to add the path to each string \
        value it encounters to the flattened dict
        """
        if isinstance(value, dict):
            for key, val in value.items():
                new_path = "{}/{}".format(path,key)
                recursive_call(val, new_path, flattened, error_list)
        elif isinstance(value, list):
            for i, val in enumerate(value):
                new_path = "{}/{}".format(path,i)
                recursive_call(val, new_path, flattened, error_list)
        elif isinstance(value, basestring):
            if value in flattened:
                error_list.append("flatten_dict: The value at {} is present more \
                    than once in the dictionary".format(path))
            flattened[value] = path
        else:
            error_list.append("flatten_dict: Value of invalid type at {},\
                value ignored. Should be dict, list or basestring".format(path))

    path = ""
    flattened = {}
    error_list = []
    if dictionary:
        recursive_call(dictionary, path, flattened, error_list)

    if error_list:
        # There was at least one error.
        error_list = ["Errors encountered while flattening:"] + error_list
        raise Exception('\n\t'.join(error_list))

    return flattened

请注意,我不太喜欢这种解决方案,因为您会丢失确切的错误类型,并且不会在错误发生时引发错误。某些日志记录或指示所需行为的标志(忽略/日志/异常)可能更可取,具体取决于您的应用程序以及谁将使用它。

寻找你感兴趣的贴纸↓↓↓
豫ICP备18024241号-1