如何进行并行的HTTP请求

3 投票
2 回答
1002 浏览
提问于 2025-04-18 10:00

我有一份包含100个ID的列表,我需要对每个ID进行查找。每次查找大约需要3秒钟。下面是我需要运行的顺序代码:

ids = [102225077, 102225085, 102225090, 102225097, 102225105, ...]
for id in ids:
    run_updates(id)

我想同时运行十个查找,可以使用gevent或者多进程。请问我该怎么做?我尝试过用gevent,但速度很慢:

def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

ids = [102225077, 102225085, 102225090, 102225097, 102225105, ...]

if __name__ == '__main__':
    for list_of_ids in list(chunks(ids, 10)):
    jobs = [gevent.spawn(run_updates(id)) for id in list_of_ids]
    gevent.joinall(jobs, timeout=200)

怎样才能把ID列表分成几部分,每次运行十个呢?我对使用多进程或gevent都不太熟悉,但都可以尝试。

如果按顺序执行,处理100个ID需要364秒。

使用多进程处理100个ID大约需要207秒,每次处理5个:

pool = Pool(processes=5)
pool.map(run_updates, list_of_apple_ids)

使用gevent的速度介于两者之间:

jobs = [gevent.spawn(run_updates, apple_id) for apple_id in list_of_apple_ids]

有没有办法比Pool.map获得更好的性能?我这台电脑性能不错,网络连接也很快,应该能更快完成这个任务...

2 个回答

0
from multiprocessing import Process
from random import Random.random

ids = [random() for _ in range(100)] # make some fake ids, whatever

def do_thing(arg): 
    print arg # Here's where you'd do lookup 

while ids: 
    curs, ids = ids[:10], ids[10:]
    procs = [Process(target=do_thing, args=(c,)) for c in curs]
    for proc in procs: 
        proc.run()

大概就是我会这么做吧。

0

可以看看这个 grequests 库。你可以这样做:

import grequests


for list_of_ids in list(chunks(ids, 10)):
    urls = [''.join(('http://www.example.com/id?=', id)) for id in list_of_ids]
    requests = (grequests.get(url) for url in urls)
    responses = grequests.map(requests)

    for response in responses:
        print response.content

我知道这样可能会打乱你的模型,因为你的请求是放在一个叫 run_updates 的方法里的,但我觉得还是值得一试。

撰写回答