httplib
和urllib2
是不线程安全的。
urllib2
不提供到全局(共享) OpenerDirector
对象,它被用来由urllib2.urlopen()
串行访问。
类似地,httplib
不提供对HTTPConnection
对象的串行化访问(即通过使用线程安全连接池),因此在线程之间共享对象是不安全的。
如果需要线程安全性,我建议使用httplib2或urllib3作为替代方案。
一般来说,如果一个模块的文档没有提到线程安全性,我会认为它不是线程安全的。您可以查看模块的源代码进行验证。
在浏览源代码,以确定一个模块是否是线程安全的,你 可以通过查看从 threading
或multiprocessing
模块,或使用queue.Queue
线程同步原语的应用启动。
UPDATE
这里是urllib2.py
(Python的2.7.2)相关的源代码片段:
_opener = None
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
global _opener
if _opener is None:
_opener = build_opener()
return _opener.open(url, data, timeout)
def install_opener(opener):
global _opener
_opener = opener
有一个明显的竞争条件,当并发线程调用install_opener()
和urlopen()
。
另外,还要注意调用urlopen()
与Request
对象为url
参数可以发生变异的Request
对象(见来源OpenerDirector.open()
),所以它不是安全的同时调用urlopen()
与共享Request
对象。
总而言之,urlopen()
是线程安全的,如果满足以下条件:
install_opener()
不是从另一个线程调用。
- A 非共享
Request
对象或字符串用作url
参数。
@Gregg - 你可以说一下如何通过检查特定模块的代码来确定线程安全吗?我经常有这个确切的问题... – 2011-04-28 22:23:47
@ire_and_curses:我相应地扩展了我的答案。 – Gregg 2011-04-29 01:42:47
谢谢 - 我的+1。 – 2011-04-29 16:47:11