Повторное использование соединений в Django с Python Requests

Как правильно использовать Python Requests для подключения в Django через несколько HTTP-запросов. Вот чем я сейчас занимаюсь:

import requests

def do_request(data):
    return requests.get('http://foo.bar/', data=data, timeout=4)

def my_view1(request)
    req = do_request({x: 1})
    ...

def my_view2(request)
    req = do_request({y: 2})
    ...

Итак, у меня есть одна функция, которая делает запрос. Эта функция вызывается в различных представлениях Django. Представления вызываются в отдельных HTTP-запросах пользователями. Мой вопрос: автоматически ли Python Requests использует одни и те же соединения (через пул соединений urllib3)?

Или мне сначала нужно создать объект сеанса Requests для работы?

s = requests.Session()  

def do_request(data):
    return s.get('http://foo.bar/', data=data, auth=('user', 'pass'), timeout=4).text

И если так, должен ли объект сеанса создаваться в глобальной области видимости или он должен находиться внутри функции?

def do_request(data):
    s = requests.Session()  
    return s.get('http://foo.bar/', data=data, auth=('user', 'pass'), timeout=4).text

У меня может быть несколько HTTP-запросов одновременно, поэтому решение должно быть безопасным для работы с потоками... Я новичок в создании пулов соединений, поэтому я действительно не уверен, и документы Requests здесь не так уж и обширны.

2 ответа

Решение

Создайте сеанс, сохраняйте сеанс, передавая его через функции и возвращая его, или создавайте объект сеанса на глобальном уровне или на уровне класса, чтобы последнее состояние сохранялось при каждом обращении к нему. И это будет работать как шарм.

В целях безопасности потоков не храните глобальный объект Session. Они должны быть в основном безопасными, но по этому поводу ведутся нерешенные дискуссии. См. Является ли объект Session из библиотеки Python Requests потокобезопасным?и Контракт потоковой передачи документов для класса сеанса № 2766.

Тем не менее, с целью повторного использования соединений должно быть безопасно хранить глобальный экземпляр HTTPAdapter, класс, фактически управляющий базовыми urllib3 PoolManager и ConnectionPool.

Установите адаптер в свои сеансы и, возможно, используйте сеансы из класса обслуживания для более легкого доступа и настройки.

      import atexit
import requests.adapters

adapter = requests.adapters.HTTPAdapter()
# Fix ResourceWarning, but at interpreter exit
# the connections are about to be closed anyway
atexit.register(adapter.close)


class FooService():
    URL = "http://foo.bar/"

    def __init__(self):
        self.session = requests.Session()
        self.session.mount("http://", adapter)  # <------ THIS

    def get_bar(self, data):
        return self.session.get(self.URL, data)


def my_view1(request)
    foo = FooService()
    foo.get_bar({"y": 1})
    # ...


def my_view2(request)
    foo = FooService()
    for y in range(1234):
        foo.get_bar({"y": y})
    # ...
Другие вопросы по тегам