python urllib2.install_opener在多线程中是否有效
高洛峰
高洛峰 2016-10-26 17:06:53
[Python讨论组]

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

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全部回复(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,一方面线程安全,另一方面使用简单。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号