python urllib2.install_opener在多线程中是否有效

新手上路,请多包涵

初学python,在写爬虫的时候希望通过代理来抓取数据,防止本机IP被封,于是开始使用自定义opener。
问题来了,既然同一个进程的多个线程内存共享,那么调用urllib2.install_opener之后,是否意味着这个进程中的所有urllib2的open请求都会用同一个opener来实现?
如果希望分开使用不同的opener的话是不是只能考虑多进程了。。?

阅读 3.3k
1 个回答

urllib2不是线程安全的,并且opener更是共享的全局变量,如下urlib2.py(python2.7.5)代码:

#/usr/lib64/python2.7/urllib2.py
122 _opener = None                                                                                                                                   
123 def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):                                                                             
124     global _opener                                                                                                                               
125     if _opener is None:                                                                                                                          
126         _opener = build_opener()                                                                                                                 
127     return _opener.open(url, data, timeout)                                                                                                      
128                                                                                                                                                  
129 def install_opener(opener):                                                                                                                      
130     global _opener                                                                                                                               
131     _opener = opener       

如果要在多线程里使用urllib需要保证install_opener不会被在多线程中同时调用,最好是在主线程安装opener。

如果要在多个线程中使用不同的opener,除了多进程外,还可以在各个子线程内创建自己的opener,
然后使用各自opener的open函数进行url访问。如下:

# 不同的opener作为线程处理函数的参数,并通过urllib2.build_opener创建线程自己的opener。
def thread_func(opener):
    thread_opener = urllib2.build_opener(opener, other_default_opener)
    ret = thread_opener.open('http://www.baidu.com')
    # ...

最后针对这类url访问的任务比较推荐使用urlib3和requests,一方面线程安全,另一方面使用简单。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题