Python grequests 以什么方式异步?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16015749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In what way is grequests asynchronous?
提问by cacois
I've been using the python requests library for some time, and recently had a need to make a request asynchronously, meaning I would like to send off the HTTP request, have my main thread continue to execute, and have a callback called when the request returns.
我已经使用 python requests 库有一段时间了,最近需要异步发出请求,这意味着我想发送 HTTP 请求,让我的主线程继续执行,并在请求返回。
Naturally, I was lead to the grequests library (https://github.com/kennethreitz/grequests), but i'm confused about the behavior. For example:
当然,我被引导到 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
The above code will produce the following output:
上面的代码将产生以下输出:
<...large HTTP response output...>
0
1
2
3
4
5
6
7
8
9
The grequests.map() call obviously blocks until the HTTP response is available. It seems likely I misunderstood the 'asynchronous' behavior here, and the grequests library is just for performing multiple HTTP requests concurrently and sending all responses to a single callback. Is this accurate?
grequests.map() 调用显然会阻塞,直到 HTTP 响应可用。我似乎误解了此处的“异步”行为,grequests 库仅用于同时执行多个 HTTP 请求并将所有响应发送到单个回调。这是准确的吗?
采纳答案by Martijn Pieters
.map()is meant to run retrieval of several URLs in parallel, and will indeed wait for these tasks to complete (gevent.joinall(jobs)) is called).
.map()旨在并行运行多个 URL 的检索,并且确实会等待这些任务完成 ( gevent.joinall(jobs)) 被调用)。
Use .send()instead to spawn jobs, using a Poolinstance:
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
Without the pool the .send()call will block still, but only for the gevent.spawn()call it executes.
如果没有池,.send()调用将仍然阻塞,但仅限于gevent.spawn()它执行的调用。
回答by Winand
Create a list of requests and then send them with .imap:
创建一个请求列表,然后使用以下命令发送它们.imap:
event_list = [grequests.get(url_viol_card, params={"viol": i},
session=session) for i in print_ev_list]
for r in grequests.imap(event_list, size=5):
print(r.request.url)
sessionisrequests.Session()object (optional)size=5send 5 requests simultaneously: as soon as one of them is completed the next one is sent- In this example when any request (unordered) is completed its url is printed
session是requests.Session()对象(可选)size=5同时发送 5 个请求:其中一个请求完成后立即发送下一个请求- 在这个例子中,当任何请求(无序)完成时,它的 url 被打印出来
回答by kylebebak
If you don't want to use grequestsyou can just implement requests with callbacks using requests+ the threadingmodule from the standard library. It's actually really easy, and if all you want to do is send requests with callbacks the API is nicer than the one provided by grequests.
如果您不想使用,grequests您可以使用requests+threading标准库中的模块来实现带有回调的请求。这实际上非常简单,如果您只想发送带有回调的请求,那么 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()
You can verify that it works like an AJAX calls in JS: you send a request on another thread, do some stuff on the main thread, and when the request returns you invoke a callback. This callback just prints out the response content.
你可以验证它是否像 JS 中的 AJAX 调用一样工作:你在另一个线程上发送一个请求,在主线程上做一些事情,当请求返回时你调用一个回调。这个回调只是打印出响应内容。
async_request('get', 'http://httpbin.org/anything', callback=lambda r: print(r.json()))
for i in range(10):
print(i)

