Асинхронные запросы с запросами Python
Я попробовал образец, предоставленный в документации библиотеки запросов для python:
http://docs.python-requests.org/en/latest/user/advanced/#asynchronous-requests
с async.map(rs)
Я получаю коды ответов, но хочу получить содержимое каждой запрошенной страницы.
out = async.map(rs)
print out[0].content
например, просто не работает.
Ответы
Ответ 1
Примечание
Нижеприведенный ответ не применим к запросам v0.13.0+. После этого вопроса асинхронная функциональность была перенесена на grequests. Однако вы можете просто заменить requests
на grequests
ниже, и он должен работать.
Я оставил этот ответ так, чтобы он отражал исходный вопрос, который касался использования запросов < v0.13.0.
Чтобы выполнить несколько задач с помощью async.map
асинхронно, вам необходимо:
- Определите функцию для того, что вы хотите делать с каждым объектом (ваша задача)
- Добавьте эту функцию как крючок события в свой запрос
- Вызовите
async.map
список всех запросов/действий
Пример:
from requests import async
# If using requests > v0.13.0, use
# from grequests import async
urls = [
'http://python-requests.org',
'http://httpbin.org',
'http://python-guide.org',
'http://kennethreitz.com'
]
# A simple task to do to each response object
def do_something(response):
print response.url
# A list to hold our things to do via async
async_list = []
for u in urls:
# The "hooks = {..." part is where you define what you want to do
#
# Note the lack of parentheses following do_something, this is
# because the response will be used as the first argument automatically
action_item = async.get(u, hooks = {'response' : do_something})
# Add the task to our list of things to do via async
async_list.append(action_item)
# Do our list of things to do via async
async.map(async_list)
Ответ 2
async
теперь является независимым модулем: grequests
.
Смотрите здесь: https://github.com/kennethreitz/grequests
И там: Идеальный метод для отправки нескольких HTTP-запросов через Python?
Установка:
$ pip install grequests
Использование:
построить стек:
import grequests
urls = [
'http://www.heroku.com',
'http://tablib.org',
'http://httpbin.org',
'http://python-requests.org',
'http://kennethreitz.com'
]
rs = (grequests.get(u) for u in urls)
отправить стек
grequests.map(rs)
Результат выглядит как
[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>]
grequests, похоже, не устанавливают ограничение для одновременных запросов, то есть когда несколько запросов отправляются на один и тот же сервер.
Ответ 3
возможно requests-futures - еще один выбор.
from requests_futures.sessions import FuturesSession
session = FuturesSession()
# first request is started in background
future_one = session.get('http://httpbin.org/get')
# second requests is started immediately
future_two = session.get('http://httpbin.org/get?foo=bar')
# wait for the first request to complete, if it hasn't already
response_one = future_one.result()
print('response one status: {0}'.format(response_one.status_code))
print(response_one.content)
# wait for the second request to complete, if it hasn't already
response_two = future_two.result()
print('response two status: {0}'.format(response_two.status_code))
print(response_two.content)
Также рекомендуется офисный документ. Если вы не хотите включать gevent, это хороший.
Ответ 4
Я тестировал запросы-фьючерсы и grequests. Grequests быстрее, но приносит исправления обезьян и дополнительные проблемы с зависимостями. Запросы-фьючерсы в несколько раз медленнее, чем grequests. Я решил написать свои собственные и просто завернутые запросы в ThreadPollExecutor, и это было почти так же быстро, как grequests, но без внешних зависимостей.
import requests
import concurrent.futures
def get_urls():
return ["url1","url2"]
def load_url(url, timeout):
return requests.get(url, timeout = timeout)
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
future_to_url = {executor.submit(load_url, url, 10): url for url in get_urls()}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
resp_err = resp_err + 1
else:
resp_ok = resp_ok + 1
Ответ 5
Я знаю, что это было закрыто на некоторое время, но я подумал, что было бы полезно продвинуть еще одно асинхронное решение, основанное на библиотеке запросов.
list_of_requests = ['http://moop.com', 'http://doop.com', ...]
from simple_requests import Requests
for response in Requests().swarm(list_of_requests):
print response.content
Документы находятся здесь: http://pythonhosted.org/simple-requests/
Ответ 6
threads=list()
for requestURI in requests:
t = Thread(target=self.openURL, args=(requestURI,))
t.start()
threads.append(t)
for thread in threads:
thread.join()
...
def openURL(self, requestURI):
o = urllib2.urlopen(requestURI, timeout = 600)
o...
Ответ 7
Я использую python-запросы для асинхронных вызовов против github gist API в течение некоторого времени.
Для примера см. код здесь:
https://github.com/davidthewatson/flasgist/blob/master/views.py#L60-72
Этот стиль python может быть не самым ярким примером, но я могу заверить вас, что код работает. Дайте мне знать, если это вас смущает, и я задокументирую это.
Ответ 8
Я также пробовал некоторые вещи, используя асинхронные методы в python, как бы то ни было, мне гораздо повезло, используя скрученные для асинхронного программирования. Он имеет меньше проблем и хорошо документирован. Вот ссылка чего-то похожего на то, что вы пытаетесь искривить.
http://pythonquirks.blogspot.com/2011/04/twisted-asynchronous-http-request.html