grequest异步的方式是什么?

cac*_*ois 39 python gevent python-requests grequests

我一直在使用python请求库,最近需要异步发出请求,这意味着我想发送HTTP请求,让我的主线程继续执行,并在调用时调用请求返回.

当然,我是通往grequests库(https://github.com/kennethreitz/grequests),但我对这种行为感到困惑.例如:

import grequests

def print_res(res):
    from pprint import pprint
    pprint (vars(res))

req = grequests.get('http://www.codehenge.net/blog', hooks=dict(response=print_res))
res = grequests.map([req])

for i in range(10):
    print i
Run Code Online (Sandbox Code Playgroud)

上面的代码将产生以下输出:

<...large HTTP response output...>

0
1
2
3
4
5
6
7
8
9
Run Code Online (Sandbox Code Playgroud)

grequests.map()调用显然会阻塞,直到HTTP响应可用.我似乎错误地理解了这里的"异步"行为,而grequest库只是用于同时执行多个HTTP请求并将所有响应发送到单个回调.这准确吗?

Mar*_*ers 53

.map()意味着并行运行几个URL的检索,并且确实会等待这些任务完成(gevent.joinall(jobs))被调用).

使用.send(),而不是产卵的工作,使用Pool实例:

req = grequests.get('http://www.codehenge.net/blog', hooks=dict(response=print_res))
job = grequests.send(req, grequests.Pool(1))

for i in range(10):
    print i
Run Code Online (Sandbox Code Playgroud)

如果没有池,.send()呼叫将会阻塞,但仅限于gevent.spawn()它执行的呼叫.

  • 啊,我现在明白了.这很完美,谢谢! (4认同)
  • @martijn pieters 你能提供一个带有帖子的样本吗?无法通过后期调用使其正常工作 (2认同)

kyl*_*bak 7

如果您不想使用,grequests您可以使用标准库中的requests+ threading模块实现带回调的请求.它实际上非常简单,如果您只想发送带有回调的请求,那么API比提供的API更好grequests.

from threading import Thread

from requests import get, post, put, patch, delete, options, head



request_methods = {
    'get': get,
    'post': post,
    'put': put,
    'patch': patch,
    'delete': delete,
    'options': options,
    'head': head,
}


def async_request(method, *args, callback=None, timeout=15, **kwargs):
    """Makes request on a different thread, and optionally passes response to a
    `callback` function when request returns.
    """
    method = request_methods[method.lower()]
    if callback:
        def callback_with_args(response, *args, **kwargs):
            callback(response)
        kwargs['hooks'] = {'response': callback_with_args}
    kwargs['timeout'] = timeout
    thread = Thread(target=method, args=args, kwargs=kwargs)
    thread.start()
Run Code Online (Sandbox Code Playgroud)

您可以验证它是否像JS中的AJAX调用一样工作:您在另一个线程上发送请求,在主线程上执行某些操作,并在请求返回时调用回调.此回调只打印出响应内容.

async_request('get', 'http://httpbin.org/anything', callback=lambda r: print(r.json()))
for i in range(10):
    print(i)
Run Code Online (Sandbox Code Playgroud)