Безопасны ли потоки urllib2 и httplib? - PullRequest
20 голосов
/ 29 апреля 2011

Я ищу информацию о безопасности потоков urllib2 и httplib.Официальная документация (http://docs.python.org/library/urllib2.html и http://docs.python.org/library/httplib.html) не содержит никакой информации на эту тему; слово thread там даже не упоминается ...

ОБНОВЛЕНИЕ

Хорошо, они не являются поточно-ориентированными из коробки. Что требуется, чтобы сделать их поточно-ориентированными, или существует сценарий, в котором они могут быть поточно-ориентированными? Я спрашиваю, потому что кажется, что

  • с использованием отдельных OpenerDirector в каждом потоке
  • без совместного использования HTTP-соединения между потоками

будет достаточно для безопасного использования этих библиотек в потокахАналогичный сценарий использования был предложен в вопросе urllib2 и безопасность потока в Cookielib

1 Ответ

41 голосов
/ 29 апреля 2011

httplib и urllib2 не потокобезопасны.

urllib2 не обеспечивает сериализованный доступ к глобальной (общей) OpenerDirector объект, который используется urllib2.urlopen().

Аналогичным образом, httplib не обеспечивает сериализованный доступ к HTTPConnection объектам (т. Е. С помощью потокового пула соединений), поэтому совместное использование HTTPConnection объектов между потоками небезопасно.

Я предлагаю использовать httplib2 или urllib3 в качестве альтернативы, если требуется безопасность потоков.

Как правило, если в документации модуля не упоминается потокобезопасность , я бы предположил, что он не потокобезопасен. Вы можете посмотреть исходный код модуля для проверки.

При просмотре исходного кода, чтобы определить, является ли модуль потокобезопасным, вы можно начать с поиска использования примитивов синхронизации потоков из threading или multiprocessing модулей, или использование 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...