urllib2 和 cookielib 的线程安全性
根据我了解到的情况,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 个回答
我跟你有一样的问题。如果你不使用pycurl的话,我觉得你在每次使用urllib2.urlopen之前,应该先执行urllib2.install_opener(self.opener)。
也许我也应该使用pycurl,因为urllib2并不是那么聪明。
你可以查看这个库的实现,路径是 [python_install_path]/lib/cookielib.py
,来确保 cookielib.CookieJar
是线程安全的。
这意味着如果你在不同的线程中共享一个 CookieJar
的实例,你不会遇到读取 Cookie 集时的不一致问题,因为 CookieJar
在内部使用了一个锁 self._cookies_lock
。
你想使用 pycurl,这是一个可以让你在Python中使用 libcurl 的工具。它是线程安全的,支持 cookies、https 等等。虽然它的使用方式有点奇怪,但只要多用几次就能习惯了。
我只用过 pycurl 来处理 HTTPBasicAuth 和 SSL,但我找到一个使用 pycurl 和 cookies 的例子,你可以在 这里查看。我记得你需要更新 pycurl.COOKIEFILE(第74行)和 pycurl.COOKIEJAR(第82行),给它们起个独特的名字(可以用 id(self.crl)
来生成)。
我记得每次请求时,你都需要创建一个新的 pycurl.Curl()
,这样才能保持线程安全。