httplib
and urllib2
are not线程安全。
urllib2
不提供对全局(共享)的序列化访问OpenerDirector
对象,它被使用urllib2.urlopen()
.
相似地,httplib
不提供序列化访问HTTPConnection
对象(即通过使用线程安全的连接池),因此共享HTTPConnection
线程之间的对象不安全。
我建议使用httplib2 or urllib3如果需要线程安全,则作为替代方案。
一般来说,如果一个模块的文档没有提到线程安全,我认为它不是线程安全的。您可以查看该模块的源代码进行验证。
当浏览源代码以确定模块是否是线程安全时,您
可以从寻找线程同步原语的使用开始threading
or 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()
and urlopen()
.
另请注意,调用urlopen()
with a Request
对象作为url
参数可能会改变Request
对象(请参阅来源OpenerDirector.open()),所以并发调用是不安全的urlopen()
与一个共享的Request
object.
总而言之,urlopen()
如果满足以下条件,则线程安全:
-
install_opener()
不是从另一个线程调用的。
- A 非共享
Request
对象或字符串用作url
范围。