实用指南

在Web开发或数据抓取过程中,我们经常需要同时向多个服务器发送HTTP请求。Python提供了多种方法来实现并发请求,从而提高程序的执行效率。本文将介绍几种实用的并发请求技术,并给出示例代码。

python并发执行request请求_多线程

1. 使用threading模块

Python的threading模块允许我们创建多线程程序。然而,由于Python的全局解释器锁(GIL),多线程在CPU密集型任务上可能并不会带来性能提升。但在I/O密集型任务(如网络请求)上,多线程仍然是一个有效的选择。

示例代码:

import threading  
import requests  
  
def fetch_url(url):  
    response = requests.get(url)  
    print(f"Got response from {url}: {response.status_code}")  
  
urls = [  
    'http://example.com/1',  
    'http://example.com/2',  
    # ... 更多URL  
]  
  
threads = []  
for url in urls:  
    t = threading.Thread(target=fetch_url, args=(url,))  
    t.start()  
    threads.append(t)  
  
# 等待所有线程完成  
for t in threads:  
    t.join()

2. 使用asyncioaiohttp

对于异步编程,Python 3.5及以上版本引入了asyncio库。aiohttp是一个基于asyncio的HTTP客户端/服务器库,非常适合并发请求。

示例代码:

import asyncio  
import aiohttp  
  
async def fetch_url(session, url):  
    async with session.get(url) as response:  
        print(f"Got response from {url}: {response.status}")  
  
async def main():  
    async with aiohttp.ClientSession() as session:  
        tasks = []  
        urls = [  
            'http://example.com/1',  
            'http://example.com/2',  
            # ... 更多URL  
        ]  
        for url in urls:  
            task = asyncio.create_task(fetch_url(session, url))  
            tasks.append(task)  
  
        # 等待所有任务完成  
        await asyncio.gather(*tasks)  
  
# Python 3.7+ 可以用下面的方式运行main函数  
asyncio.run(main())

3. 使用concurrent.futures

concurrent.futures模块提供了高级接口,用于异步执行可调用对象。ThreadPoolExecutor用于多线程,而ProcessPoolExecutor用于多进程(但请注意,多进程在I/O密集型任务上可能不如多线程有效,且存在更多的开销)。

示例代码(使用ThreadPoolExecutor):

import concurrent.futures  
import requests  
  
def fetch_url(url):  
    response = requests.get(url)  
    print(f"Got response from {url}: {response.status_code}")  
  
urls = [  
    'http://example.com/1',  
    'http://example.com/2',  
    # ... 更多URL  
]  
  
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:  
    futures = {executor.submit(fetch_url, url): url for url in urls}  
  
    for future in concurrent.futures.as_completed(futures):  
        url = futures[future]  
        try:  
            # 如果fetch_url抛出异常,则捕获它  
            data = future.result()  
        except Exception as exc:  
            print(f'Generated an exception for {url}: {exc}')

注意事项:

  • 在并发请求时,请确保遵守目标网站的robots.txt文件和服务条款,避免对服务器造成过大的负载。
  • 并发请求可能会增加网络带宽的使用,请确保您的网络环境可以支持这种使用模式。
  • 不同的并发策略在不同的应用场景下可能有不同的效果,请根据您的实际需求选择合适的策略。