簡體   English   中英

Python pickle實例沒有屬性

[英]Python pickle instance has no attribute

我正在嘗試抓取網站。 在此網站中,我將已爬網的人員存儲在person_set中,並將用於爬網下一個人員的隊列存儲在parse_queue中。 在開始每個人爬網時,我需要將這兩個數據結構寫入文件中,以防由於異常或連接不良而導致爬網中斷,因此我可以稍后繼續。

我有三個python文件。 主文件,蜘蛛和人物模型。 Main實例化Spider,Spider開始解析,並在必要時調用write和read。 人員文件具有“人員”類,該類是用於存儲人員數據的模型。

我在讀取我寫的數據時遇到問題。 我檢查了許多有關此錯誤的問題,這似乎是導入問題。 但是,即使我將Person類導入到main和spider中,它仍然給我錯誤。 看來Emergency_read方法不受我的頂級導入的影響。

main.py

from spiders import Spider
from person import Person
import pickle

def main():
    ....
    spider = Spider("seed_input")
    spider.parse(client)

spiders.py

import pickle
from person import Person

class Spider:

    def __init__(self, filename):
            self.person_set = Set()

            self.file_to_seed(filename)
            for seed_url in self.seed_list:
                    self.seed_to_parse_queue(seed_url)

    def parse(self, client):
        if os.path.exists('tmp.person_set'):
                print "Program wasnt ended properly, continuing from where it left"
                self.emergency_read()

        ... starts parsing

    def emergency_write(self):

        if os.path.exists('tmp.person_set'):
            self.delete_emergency_files()

        with open('tmp.person_set', 'wb') as f:
            pickle.dump(self.person_set, f)

        with open('tmp.parse_queue', 'wb') as f:
            pickle.dump(self.parse_queue, f)

    def emergency_read(self):
        with open('tmp.person_set', 'rb') as f:
            self.person_set = pickle.load(f)

        with open('tmp.parse_queue', 'rb') as f:
            self.parse_queue = pickle.load(f)

person.py

class Person:

    def __init__(self, name):
            self.name = name
            self.friend_set = Set()
            self.profile_url = ""
            self.id = 0
            self.color = "Grey"
            self.parent = None
            self.depth = 0

    def add_friend(self, friend):
            self.friend_set.add(friend)

    def __repr__(self):
            return "Person(%s, %s)" % (self.profile_url, self.name)

    def __eq__(self, other):
            if isinstance(other, Person):
                return ((self.profile_url == other.profile_url) and (self.name == other.name))
            else:
                return False

    def __ne__(self, other):
            return (not self.__eq__(other))

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

堆棧跟蹤

python main.py 
Program wasnt ended properly, continuing from where it left
Traceback (most recent call last):
File "main.py", line 47, in <module>
main()
File "main.py", line 34, in main
spider.parse(client)
File "/home/ynscn/py-workspace/lll/spiders.py", line 39, in parse
self.emergency_read()
File "/home/ynscn/py-workspace/lll/spiders.py", line 262, in emergency_read
self.person_set = pickle.load(f)
File "/usr/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1198, in load_setitem
dict[key] = value
File "/home/ynscn/py-workspace/lll/person.py", line 30, in __hash__
return hash(self.__repr__())
File "/home/ynscn/py-workspace/lll/person.py", line 18, in __repr__
return "Person(%s, %s)" % (self.profile_url, self.name)
AttributeError: Person instance has no attribute 'profile_url'

Pickle以不確定的順序加載類實例的組件。 在加載期間但在反序列化Person.profile_url屬性之前,會發生此錯誤。 請注意,它在load_setitem期間load_setitem ,這意味着它可能正在嘗試加載friend_set屬性(該屬性是一個集合)。

您的自定義__repr__()依賴於class屬性,然后您的自定義__hash__()pickle需要)依賴於__repr__()

我的建議是使用Python的默認__hash__方法。 那行得通嗎?

如果使用dill而不是pickle您的代碼可能會按原樣進行序列化。 dill可以腌制類對象,實例,方法和屬性……以及python中的大多數內容。 dill還可以為類和類實例存儲動態修改的狀態。 我同意@nofinator指出,這似乎是一個泡菜load錯誤。 但是, dill可能會繞開它。

可能更好的是,如果您想強制執行裝載和卸載的命令,則可以嘗試添加__getstate____setstate__方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM