urllib2 和 cookielib 的线程安全性

3 投票
3 回答
1611 浏览
提问于 2025-04-16 00:26

根据我了解到的情况,cookielib 这个库似乎不支持多线程使用;不过,那个说法已经有五年了,所以可能不准确。

尽管如此,我还是在想——

如果我为每个工作线程创建一个这样的类:

class Acc:
    jar = cookielib.CookieJar()
    cookie = urllib2.HTTPCookieProcessor(jar)       
    opener = urllib2.build_opener(cookie)

    headers = {}
    def __init__ (self,login,password):
        self.user = login
        self.password = password

    def login(self):
        return False # Some magic, irrelevant

    def fetch(self,url):
        req = urllib2.Request(url,None,self.headers)
        res = self.opener.open(req)
        return res.read()

这样做可以吗?(或者有没有更好的方法?)每个线程都会使用自己的账户,所以工作线程之间不共享 cookies 也不是问题。

3 个回答

1

我跟你有一样的问题。如果你不使用pycurl的话,我觉得你在每次使用urllib2.urlopen之前,应该先执行urllib2.install_opener(self.opener)。

也许我也应该使用pycurl,因为urllib2并不是那么聪明。

2

你可以查看这个库的实现,路径是 [python_install_path]/lib/cookielib.py,来确保 cookielib.CookieJar 是线程安全的

这意味着如果你在不同的线程中共享一个 CookieJar 的实例,你不会遇到读取 Cookie 集时的不一致问题,因为 CookieJar 在内部使用了一个锁 self._cookies_lock

2

你想使用 pycurl,这是一个可以让你在Python中使用 libcurl 的工具。它是线程安全的,支持 cookies、https 等等。虽然它的使用方式有点奇怪,但只要多用几次就能习惯了。

我只用过 pycurl 来处理 HTTPBasicAuth 和 SSL,但我找到一个使用 pycurl 和 cookies 的例子,你可以在 这里查看。我记得你需要更新 pycurl.COOKIEFILE(第74行)和 pycurl.COOKIEJAR(第82行),给它们起个独特的名字(可以用 id(self.crl) 来生成)。

我记得每次请求时,你都需要创建一个新的 pycurl.Curl(),这样才能保持线程安全。

撰写回答