用循环腌制图形

Jas*_*ond 6 python graph pickle

我在python中有一个自定义节点类,它构建在一个图形(这是一个字典)中.由于这些需要花费一些时间来创建,我想要腌制它们,这样我每次运行代码时都不必重新构建它们.

不幸的是,因为这个图有周期,所以cPickle会达到最大递归深度:

RuntimeError:在对对象进行pickle时超出了最大递归深度

这是我的节点对象:

class Node:
    def __init__(self, name):
        self.name = name
        self.uid = 0
        self.parents = set()
        self.children = set()

    def __hash__(self):
        return hash(self.name)

    def __eq__(self, that):
        return self.name == that.name

    def __str__(self):
        return "\n".join(["Name: " + self.name,
                          "\tChildren:" + ", ".join([c.name for c in self.children]),
                          "\tParents:" + ", ".join([p.name for p in self.parents])
                          ]
                         )
Run Code Online (Sandbox Code Playgroud)

这是我构建图表的方式:

def buildGraph(input):
    graph = {}
    idToNode = {}

    for line in input:
        ## Input from text line by line looks like
        ## source.node -> target.node
        source, arr, target = line.split()
        if source in graph:
            nsource = graph[source]
        else:
            nsource = Node(source)
            nsource.uid = len(graph)
            graph[source] = nsource
            idToNode[nsource.uid] = nsource

        if target in graph:
            ntarget = graph[target]
        else:
            ntarget = Node(target)
            ntarget.uid = len(graph)
            graph[target] = ntarget
            idToNode[ntarget.uid] = ntarget

        nsource.children.add(ntarget)
        ntarget.parents.add(nsource)
    return graph
Run Code Online (Sandbox Code Playgroud)

然后在我的主要,我有

    graph = buildGraph(input_file)
    bo = cPickle.dumps(graph)
Run Code Online (Sandbox Code Playgroud)

第二行是我得到递归深度错误的地方.

除了改变Node的结构之外还有其他解决方案吗?

Cha*_*eon 3

您需要为 pickle 准备对象:如果您有一个循环,则需要打破循环并以其他形式存储此信息。

Pickle使用方法__getstate__来准备对象以进行 pickle(之前调用)并__setstate__初始化对象。

class SomethingPickled(object):
    ## Compress and uncycle data before pickle.
    def __getstate__(self):
        # deep copy object
        state = self.__dict__.copy()
        # break cycles
        state['uncycled'] = self.yourUncycleMethod(state['cycled'])
        del state['cycle']
        # send to pickle
        return state

    ## Expand data before unpickle.
    def __setstate__(self, state):
        # restore cycles
        state['cycle'] = self.yourCycleMethod(state['uncycled'])
        del state['uncycle']
        self.__dict__.update(state)
Run Code Online (Sandbox Code Playgroud)

我相信您会找到如何打破和加入循环的想法:)