Повторное использование соединений в 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})
# ...