Python 什么';检查数千个URL的最快方法是什么?
我需要检查至少20k个url,以检查url是否已打开,并在数据库中保存一些数据 我已经知道如何检查url是否在线,以及如何在数据库中保存一些数据。但是如果没有并发性,检查所有URL将需要很长时间,那么检查数千个URL的最快方法是什么 我遵循本教程:似乎“CPU绑定的多处理版本”是最快的方法,但我想知道这是最快的方法还是有更好的选择 编辑: 根据回复,我将更新比较多处理和多线程的帖子 例1: 打印“你好!”40次 穿线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
- 带1个线程:20.152419090270996秒
- 带2个线程:10.061403036117554秒
- 带4个线程:5.040558815002441秒
- 带8个线程:2.515489101409912秒
- 花了3.1343798637390137秒
感谢您的帮助我认为您应该使用游泳池: 根据这里的一些结果: 我要说的是始终使用多处理。也许,如果您希望您的请求需要很长时间才能解决,那么线程的上下文切换优势将克服多处理的强大威力 差不多
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调度,这可能会导致数千个请求的瓶颈。虽然进程需要更长的时间来加速,但如果这种数据获取有任何意义,它将