urllib2和httplib线程安全吗?
我想了解一下 urllib2
和 httplib
的线程安全性。官方文档(http://docs.python.org/library/urllib2.html 和 http://docs.python.org/library/httplib.html)对此没有任何说明,甚至连“线程”这个词都没有提到……
更新
好的,它们默认情况下不是线程安全的。那么,要让它们线程安全需要做些什么,或者有没有什么情况可以让它们线程安全呢?我问这个是因为似乎
- 在每个线程中使用独立的
OpenerDirector
- 不在多个线程之间共享 HTTP 连接
就足以安全地在线程中使用这些库。类似的使用场景在问题 urllib2 和 cookielib 的线程安全性 中也有提到。
1 个回答
httplib
和 urllib2
是不安全的,在多线程环境下使用时可能会出问题。
urllib2
不提供对一个全局(共享的)OpenerDirector
对象的安全访问,这个对象是通过 urllib2.urlopen()
来使用的。
同样,httplib
也不提供对 HTTPConnection
对象的安全访问(也就是说,它没有使用一个线程安全的连接池),所以在多个线程之间共享 HTTPConnection
对象是不安全的。
如果你需要线程安全的功能,我建议使用 httplib2 或 urllib3 作为替代方案。
一般来说,如果一个模块的文档中没有提到线程安全,我会认为它是不安全的。你可以查看模块的源代码来确认这一点。
在查看源代码以判断一个模块是否线程安全时,可以先找找 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()
时,会出现明显的竞争条件。
另外,注意用 Request
对象作为 url
参数调用 urlopen()
可能会改变这个 Request
对象(具体可以查看 OpenerDirector.open()
的源代码),所以在多个线程中同时使用一个共享的 Request
对象调用 urlopen()
是不安全的。
总的来说,如果满足以下条件,urlopen()
是线程安全的:
- 不能从其他线程调用
install_opener()
。 - 作为
url
参数使用的是一个非共享的Request
对象或字符串。