urllib2和httplib线程安全吗?

Pio*_*ost 20 python urllib2 thread-safety httplib

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

UPDATE

好吧,它们不是开箱即用的线程安全.是什么使它们成为线程安全的,或者是否存在可以线程安全的场景?我问,因为它似乎是

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

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

Gre*_*egg 41

httpliburllib2不是线程安全的.

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

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

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

通常,如果模块的文档没有提到线程安全性,我会认为它不是线程安全的.您可以查看模块的源代码以进行验证.

在浏览源代码以确定模块是否是线程安全的时,您可以首先查找来自threadingmultiprocessing模块的线程同步原语的 使用,或者使用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
Run Code Online (Sandbox Code Playgroud)

有一个明显的竞争条件,当并发线程调用install_opener()urlopen().

另请注意,urlopen()使用Request对象作为url参数进行调用可能会使Request对象发生变异(请参阅源代码OpenerDirector.open()),因此同时urlopen()使用共享Request对象进行调用是不安全的.

总而言之,urlopen()如果满足以下条件,则是线程安全的:

  • install_opener() 不是从另一个线程调用.
  • 非共享 Request对象,或字符串被用作url参数.

  • @Piotr Dobrogost:我同意用户不应*强制*检查库的源代码,以确定它是否是线程安全的.如果开发一个具有线程安全性的库,那么我认为文档将指出这一点.如果文档没有讨论线程安全性,那么我认为库不是线程安全的.为了验证我的假设,通常需要查看图书馆的代码.关于无锁数据结构和cookielib,线程安全是一个复杂的主题,我只提供了一个在模块中寻找的基线**可能*表示它是线程安全的. (6认同)
  • 强迫用户检查库的源代码以查明给定的库是否是线程安全的想法对我来说很奇怪.有些库使用同步代码而不是线程安全的(cookielib),并且有些库不使用同步代码是线程安全的,因为它们使用无锁结构和算法. (3认同)
  • @ire_and_curses:我已经相应地扩展了我的答案. (2认同)