httplib
并且urllib2
不是线程安全的。
urllib2
不提供对全局(共享)
OpenerDirector
对象的序列化访问,该对象由urllib2.urlopen()
.
同样,httplib
不提供对HTTPConnection
对象的序列化访问(即通过使用线程安全的连接池),因此HTTPConnection
线程之间共享对象是不安全的。
如果需要线程安全,我建议使用httplib2或urllib3作为替代方案。
一般来说,如果一个模块的文档没有提到 thread-safety,我会认为它不是线程安全的。您可以查看模块的源代码进行验证。
在浏览源代码以确定一个模块是否是线程安全的时,您可以首先从
threading
或multiprocessing
模块中查找线程同步原语的用途,或queue.Queue
.
更新
这是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()
不是从另一个线程调用的。
- 非共享 对象或字符串
Request
用作url
参数。