Python 什么';检查数千个URL的最快方法是什么?

Python 什么';检查数千个URL的最快方法是什么?,python,concurrency,python-requests,Python,Concurrency,Python Requests,我需要检查至少20k个url,以检查url是否已打开,并在数据库中保存一些数据 我已经知道如何检查url是否在线,以及如何在数据库中保存一些数据。但是如果没有并发性,检查所有URL将需要很长时间,那么检查数千个URL的最快方法是什么 我遵循本教程:似乎“CPU绑定的多处理版本”是最快的方法,但我想知道这是最快的方法还是有更好的选择 编辑: 根据回复,我将更新比较多处理和多线程的帖子 例1: 打印“你好!”40次 穿线 带1个线程:20.152419090270996秒 带2个线程:10.061

我需要检查至少20k个url,以检查url是否已打开,并在数据库中保存一些数据

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

我遵循本教程:似乎“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%


感谢您的帮助

我认为您应该使用游泳池:

根据这里的一些结果:

我要说的是始终使用多处理。也许,如果您希望您的请求需要很长时间才能解决,那么线程的上下文切换优势将克服多处理的强大威力

差不多

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

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

        results=pool.map(fetch_data, urls)

编辑:为了处理关于一组子进程的注释,我已经演示了如何请求与逻辑线程数量相等的进程,我认为您应该使用池:

根据这里的一些结果:

我要说的是始终使用多处理。也许,如果您希望您的请求需要很长时间才能解决,那么线程的上下文切换优势将克服多处理的强大威力

差不多

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

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

        results=pool.map(fetch_data, urls)

编辑:为了回答关于设置数量的子进程的评论,我已经演示了如何请求与逻辑线程数量相等的进程。要说多处理始终是最佳选择,是不正确的,多处理最好只用于繁重的计算

对于不需要大量计算,但只需要输入/输出操作(如数据库请求或远程webapp api请求)的操作,最佳选择是模块线程。线程可以比多处理更快,因为多处理需要序列化数据以将其发送到子进程,同时trheads使用相同的内存堆栈

案例中的典型活动是创建输入队列。队列并将任务(案例中的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.")

说多处理永远是最好的选择是错误的,多处理最好只用于繁重的计算

对于不需要大量计算,但只需要输入/输出操作(如数据库请求或远程webapp api请求)的操作,最佳选择是模块线程。线程可以比多处理更快,因为多处理需要序列化数据以将其发送到子进程,同时trheads使用相同的内存堆栈

案例中的典型活动是创建输入队列。队列并将任务(案例中的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.")

我目前使用队列的多处理,它的工作速度足够快


与上面Artiom的解决方案类似,我将进程数设置为80(当前),使用“worker”提取数据,将其发送到队列,完成后,查看返回的结果并根据队列进行处理。

我当前使用队列的多处理,它的工作速度足以满足我的使用目的


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

使用asyncio或线程方法go使用asyncio或线程方法go使用asyncio或线程方法我将删除
processs=4
,以便
Pool
可以从
os.cpu\u count()获取值
@CircArgs您必须指定mp可能比多线程结束时慢,即使在没有繁重计算的情况下,一个线程一个进程程序也是如此。@Artion Kozyrev线程共享io调度,这可能会导致数千个请求的瓶颈。虽然进程需要更长的时间来加速,但如果这种数据获取有什么意义的话,它可能会更快,而且使用起来绝对简单multiprocessing@CircArgs在所描述的情况下,所有的重负载都在服务器端,mp模块不会使其更快,您的进程所要做的就是等待服务器的应答。如果OP需要对他想要从服务器接收的数据进行一些计算,他应该首先从服务器接收答案,然后使用mp模块处理接收到的数据。谢谢你的回复,我正在检查你给我的所有信息。你认为另一个答复如何?因为我不会写相同的内存空间,所以在这种情况下,线程可能会更好。我只是问一下,我会做一些测试来比较这两种解决方案。我会删除
processs=4
,这样
Pool
就可以从
os.cpu\u count()获得值
@CircArgs您必须指定mp可能比多线程结束时慢,即使在没有繁重计算的情况下,一个线程一个进程程序也是如此。@Artion Kozyrev线程共享io调度,这可能会导致数千个请求的瓶颈。虽然进程需要更长的时间来加速,但如果这种数据获取有任何意义,它将