如何对CookieJar进行序列化?

9 投票
2 回答
3495 浏览
提问于 2025-04-15 12:24

我有一个包含 CookieJar 的对象,我想把它保存起来。

不过,大家可能都知道,pickle 在遇到包含锁对象的东西时会出问题。而 CookieJar 里就有一个锁对象,这真让人头疼。

from cPickle import dumps
from cookielib import CookieJar

class Person(object):
    def __init__(self, name):
        self.name = name
        self.cookies = CookieJar()

bob = Person("bob")
dumps(bob)

# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# cPickle.UnpickleableError: Cannot pickle <type 'thread.lock'> objects

那我该怎么保存这个对象呢?

我想到的唯一解决办法是使用 FileCookieJar.save 和 FileCookieJar.load,把它们保存到一个字符串IO对象里。但有没有更好的方法呢?

2 个回答

7

CookieJar 这个东西并不是特别适合用来保存数据(这就是 FileCookieJar 子类主要解决的问题!),不过你可以通过遍历一个 CookieJar 实例来获取所有的 cookies(比如说,你可以把这些 cookies 列表保存起来)。如果你想根据这些 cookies 来重建这个 jar,可以对每个 cookie 使用 set_cookie 方法。这样我就可以实现保存和恢复 cookie jar 的功能,如果我需要经常使用这些功能,还可以用 copy_reg 方法来注册合适的函数。

9

这里有一个尝试,就是从CookieJar这个类派生出一个新类,并重写了pickle使用的getstate和setstate方法。我没有使用过cookieJar,所以不确定它是否可用,但你可以把这个派生类保存下来。

from cPickle import dumps
from cookielib import CookieJar
import threading

class MyCookieJar(CookieJar):
    def __getstate__(self):
        state = self.__dict__.copy()
        del state['_cookies_lock']
        return state

    def __setstate__(self, state):
        self.__dict__ = state
        self._cookies_lock = threading.RLock()

class Person(object):
    def __init__(self, name):
        self.name = name
        self.cookies = MyCookieJar()

bob = Person("bob")
print dumps(bob)

撰写回答