20

我正在寻找有关 和 的线程安全性的urllib2信息httplib。官方文档(http://docs.python.org/library/urllib2.htmlhttp://docs.python.org/library/httplib.html)缺乏关于这个主题的任何信息;那里甚至没有提到线程这个词......

更新

好的,它们不是开箱即用的线程安全的。使它们成为线程安全的要求是什么,或者是否存在它们可以是线程安全的场景?我问是因为看起来

  • OpenerDirector在每个线程中使用单独的
  • 不在线程之间共享 HTTP 连接

足以在线程中安全地使用这些库。在urllib2 和 cookielib 线程安全问题中提出了类似的使用场景

4

1 回答 1

42

httplib并且urllib2不是线程安全的

urllib2不提供对全局(共享) OpenerDirector对象的序列化访问,该对象由urllib2.urlopen().

同样,httplib不提供对HTTPConnection对象的序列化访问(即通过使用线程安全的连接池),因此HTTPConnection线程之间共享对象是不安全的。

如果需要线程安全,我建议使用httplib2urllib3作为替代方案。

一般来说,如果一个模块的文档没有提到 thread-safety,我会认为它不是线程安全的。您可以查看模块的源代码进行验证。

在浏览源代码以确定一个模块是否是线程安全的时,您可以首先从 threadingmultiprocessing模块中查找线程同步原语的用途,或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参数。
于 2011-04-28T21:56:51.103 回答