检查数千个网址的最快方法是什么?

时间:2019-10-17 11:45:20

标签: python concurrency python-requests

我需要检查至少2万个url,以检查该url是否启动并将一些数据保存在数据库中。

我已经知道如何检查url是否在线以及如何在数据库中保存一些数据。但是,如果没有并发性,检查所有URL将花费很多时间,那么检查数千个URL的最快方法是什么?

我正在遵循本教程:https://realpython.com/python-concurrency/,看来“ CPU绑定多处理版本”是最快的方法,但是我想知道这是最快的方法还是有更好的选择

编辑:

根据回复,我将更新比较多处理和多线程的帖子

示例1: 打印“你好!” 40次

线程

  • 具有1个线程:20.152419090270996秒
  • 有2个线程:10.061403036117554秒
  • 具有4个线程:5.040558815002441秒
  • 具有8个线程:2.515489101409912秒

具有8个核心的多处理:

  • 花了3.1343798637390137秒

如果使用8个线程,则线程会更好

示例2,这个问题在我的问题中提出:

经过多次测试后,如果使用12个以上线程,则线程传输速度会更快。例如,如果您要测试40个url,并且使用具有40个线程的线程,它将比具有8个内核的多处理速度快50%

感谢您的帮助

3 个答案:

答案 0 :(得分:3)

我认为您应该使用pool:pool docs

根据此处的一些结果:mp vs threading SO

我会说总是使用多重处理。也许,如果您希望您的请求花很长时间才能解决,那么线程的上下文切换优势将克服多处理的蛮力

类似

import multiprocessing as mp
urls=['google.com', 'yahoo.com']

with mp.Pool(mp.cpu_count()) as pool:

        results=pool.map(fetch_data, urls)

编辑:解决关于一定数量的子流程的注释,我已经展示了如何请求与您的逻辑线程数量相等的流程

答案 1 :(得分:2)

要说多处理永远是最好的选择,那是不正确的,多处理仅对繁重的计算才是最好的!

对于不需要大量计算但仅需执行IN / OUT操作(如数据库记录或远程Webapp api请求)的操作的最佳选择是模块线程。线程处理可能比多处理更快,因为多处理需要序列化数据以将其发送到子进程,而trhead使用相同的内存堆栈。

Threading module

这种情况下的典型活动是创建输入队列,将任务放入队列并放入任务(您的情况下为URL),并创建多个工作程序以从队列中接收任务:

import threading as thr
from queue import Queue


def work(input_q):
    """the function take task from input_q and print or return with some code changes (if you want)"""
    while True:
        item = input_q.get()
        if item == "STOP":
            break

        # else do some work here
        print("some result")


if __name__ == "__main__":
    input_q = Queue()
    urls = [...]
    threads_number = 8
    workers = [thr.Thread(target=work, args=(input_q,),) for i in range(threads_number)]
    # start workers here
    for w in workers:
        w.start

    # start delivering tasks to workers 
    for task in urls:
        input_q.put(task)

    # "poison pillow" for all workers to stop them:

    for i in range(threads_number):
        input_q.put("STOP")

    # join all workers to main thread here:

    for w in workers:
        w.join

    # show that main thread can continue

    print("Job is done.")

答案 2 :(得分:0)

我目前将“多处理与队列一起使用”,它对于我使用的目的来说足够快。

类似于上述Artiom的解决方案,我将进程数设置为80(当前),使用“工人”拉取数据,将其发送到队列中,完成后,根据返回的结果进行处理,具体取决于队列。