httplib
and urllib2
are not thread-safe.
urllib2
does not provide serialized access to a global (shared)
OpenerDirector
object, which is used by urllib2.urlopen()
.
Similarly, httplib
does not provide serialized access to HTTPConnection
objects (i.e. by using a thread-safe connection pool), so sharing HTTPConnection
objects between threads is not safe.
I suggest using httplib2 or urllib3 as an alternative if thread-safety is required.
Generally, if a module's documentation does not mention thread-safety, I would assume it is not thread-safe. You can look at the module's source code for verification.
When browsing the source code to determine whether a module is thread-safe, you
can start by looking for uses of thread synchronization primitives from the
threading
or multiprocessing
modules, or use of queue.Queue
.
UPDATE
Here is a relevant source code snippet from 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
There is an obvious race condition when concurrent threads call install_opener()
and urlopen()
.
Also, note that calling urlopen()
with a Request
object as the url
parameter may mutate the Request
object (see the source for OpenerDirector.open()
), so it is not safe to concurrently call urlopen()
with a shared Request
object.
All told, urlopen()
is thread-safe if the following conditions are met:
install_opener()
is not called from another thread.
- A non-shared
Request
object, or string is used as the url
parameter.