在python 2.7中使用pickle.dump保存的类变量字典

Joe*_*een 6 python pickle python-2.7

我正在使用pickle通过转储root来保存对象图.当我加载根时,它具有所有实例变量和连接的对象节点.但是我将所有节点保存在字典类型的类变量中.在保存之前,类变量已满,但在取消数据后,它变为空.

这是我正在使用的课程:

class Page():

    __crawled = {}

    def __init__(self, title = '', link = '', relatedURLs = []):
        self.__title = title
        self.__link = link
        self.__relatedURLs = relatedURLs
        self.__related = [] 

    @property
    def relatedURLs(self):
        return self.__relatedURLs

    @property
    def title(self):
        return self.__title

    @property
    def related(self):
        return self.__related

    @property
    def crawled(self):
        return self.__crawled

    def crawl(self,url):
        if url not in self.__crawled:
            webpage = urlopen(url).read()
            patFinderTitle = re.compile('<title>(.*)</title>')
            patFinderLink = re.compile('<link rel="canonical" href="([^"]*)" />')
            patFinderRelated = re.compile('<li><a href="([^"]*)"')

            findPatTitle = re.findall(patFinderTitle, webpage)
            findPatLink = re.findall(patFinderLink, webpage)
            findPatRelated = re.findall(patFinderRelated, webpage)
            newPage = Page(findPatTitle,findPatLink,findPatRelated)
            self.__related.append(newPage)
            self.__crawled[url] = newPage
        else:
            self.__related.append(self.__crawled[url])

    def crawlRelated(self):
        for link in self.__relatedURLs:
            self.crawl(link)
Run Code Online (Sandbox Code Playgroud)

我这样保存:

with open('medTwiceGraph.dat','w') as outf:
    pickle.dump(root,outf)
Run Code Online (Sandbox Code Playgroud)

我加载它像这样:

def loadGraph(filename): #returns root
    with open(filename,'r') as inf:
        return pickle.load(inf)

root = loadGraph('medTwiceGraph.dat')
Run Code Online (Sandbox Code Playgroud)

除了类变量__crawled之外的所有数据加载.

我究竟做错了什么?

Bak*_*riu 7

Python并没有真正挑选类对象.它只是保存他们的名字以及在哪里找到它们.来自以下文件pickle:

类似地,类通过命名引用进行pickle,因此适用于unpickling环境中的相同限制.请注意,不会对类的代码或数据进行pickle,因此在以下示例attr中,在unpickling环境中不会还原class属性:

class Foo:
    attr = 'a class attr'

picklestring = pickle.dumps(Foo)
Run Code Online (Sandbox Code Playgroud)

这些限制是必须在模块的顶层定义可选函数和类的原因.

类似地,当类实例被pickle时,它们的类的代码和数据不会与它们一起被pickle.仅腌制实例数据.这是故意完成的,因此您可以修复类中的错误或向类添加方法,并仍然加载使用该类的早期版本创建的对象.如果您计划拥有可以看到类的许多版本的长寿命对象,那么在对象中放置版本号可能是值得的,这样可以通过类的__setstate__()方法进行适当的转换.

在您的示例中,您可以将问题更改__crawled为实例属性或全局变量.


Phi*_*per 5

默认情况下,pickle 只会使用 的内容self.__dict__,而不使用self.__class__.__dict__你认为你想要的内容。

我说“你认为你想要什么”,因为取消实例不应该改变类级别的状态。

如果您想更改此行为,请查看文档中的__getstate____setstate__