2011-04-28 76 views
19

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

UPDATE

好了,他们是不是线程安全的开箱即用。 需要什么才能让它们成为线程安全的或者是否存在可以线程安全的方案? 我这么问是因为它似乎

中的HTTP连接就足以在线程安全地使用这些库。类似的使用场景是在问题提出urllib2 and cookielib thread safety

回答

40

httpliburllib2线程安全的。

urllib2不提供到全局(共享) OpenerDirector对象,它被用来由urllib2.urlopen()串行访问。

类似地,httplib不提供对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 

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

另外,还要注意调用urlopen()Request对象为url参数可以发生变异的Request对象(见来源OpenerDirector.open()),所以它不是安全的同时调用urlopen()与共享Request对象。

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

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

@Gregg - 你可以说一下如何通过检查特定模块的代码来确定线程安全吗?我经常有这个确切的问题... – 2011-04-28 22:23:47

+2

@ire_and_curses:我相应地扩展了我的答案。 – Gregg 2011-04-29 01:42:47

+0

谢谢 - 我的+1。 – 2011-04-29 16:47:11