一文带你掌握Python中多线程和线程池的使用方法

 更新时间:2023年04月18日 09:42:04   作者:小小鸟爱吃辣条  
Python中的多线程和线程池是其强大的功能之一,可以让我们更加高效地利用CPU资源,提高程序的运行速度。本文将介绍Python中多线程和线程池的使用方法,并提供一些实用的案例供读者参考

Python是一种高级编程语言,它在众多编程语言中,拥有极高的人气和使用率。Python中的多线程和线程池是其强大的功能之一,可以让我们更加高效地利用CPU资源,提高程序的运行速度。本篇博客将介绍Python中多线程和线程池的使用方法,并提供一些实用的案例供读者参考。

一、多线程

多线程是指在同一进程中,有多个线程同时执行不同的任务。Python中的多线程是通过threading模块来实现的。下面是一个简单的多线程示例:

import threading

def task(num):
    print('Task %d is running.' % num)

if __name__ == '__main__':
    for i in range(5):
        t = threading.Thread(target=task, args=(i,))
        t.start()

上述代码中,我们定义了一个task函数,它接受一个参数num,用于标识任务。在主程序中,我们创建了5个线程,每个线程都执行task函数,并传入不同的参数。通过start()方法启动线程。运行上述代码,可以看到输出结果类似于下面这样:

Task 0 is running.
Task 1 is running.
Task 2 is running.
Task 3 is running.
Task 4 is running.

由于多线程是并发执行的,因此输出结果的顺序可能会有所不同。

二、线程池

线程池是一种管理多线程的机制,它可以预先创建一定数量的线程,并将任务分配给这些线程执行。Python中的线程池是通过ThreadPoolExecutor类来实现的。下面是一个简单的线程池示例:

import concurrent.futures

def task(num):
    print('Task %d is running.' % num)

if __name__ == '__main__':
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        for i in range(5):
            executor.submit(task, i)

上述代码中,我们使用了with语句创建了一个ThreadPoolExecutor对象,其中max_workers参数指定了线程池中最大的线程数量。在主程序中,我们创建了5个任务,每个任务都通过executor.submit()方法提交给线程池执行。运行上述代码,可以看到输出结果类似于下面这样:

Task 0 is running.
Task 1 is running.
Task 2 is running.
Task 3 is running.
Task 4 is running.

由于线程池中最大的线程数量为3,因此只有3个任务可以同时执行,其他任务需要等待线程池中的线程空闲后再执行。

三、使用案例

下面是一个实际的案例,展示了如何使用多线程和线程池来加速数据处理过程。假设我们有一个包含1000个元素的列表,需要对每个元素进行某种运算,并将结果保存到另一个列表中。我们可以使用单线程的方式来实现:

def process(data):
    result = []
    for item in data:
        result.append(item * 2)
    return result

if __name__ == '__main__':
    data = list(range(1000))
    result = process(data)
    print(result)

上述代码中,我们定义了一个process函数,它接受一个列表作为参数,对列表中的每个元素进行运算,并将结果保存到另一个列表中。在主程序中,我们创建了一个包含1000个元素的列表,并将其传递给process函数。运行上述代码,可以看到输出结果类似于下面这样:

[0, 2, 4, 6, 8, ..., 1996, 1998]

Python中的多线程和线程池可以提高爬虫的效率,本文将介绍一个爬取豆瓣电影Top250的案例,并通过多线程和线程池优化爬取过程。

1.单线程爬取

首先,我们先来看一下单线程爬取的代码:

# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup


def get_html(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except Exception as e:
        print(e)


def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    movie_list = soup.find(class_='grid_view').find_all('li')

    for movie in movie_list:
        title = movie.find(class_='title').string
        rating = movie.find(class_='rating_num').string
        print(title, rating)


def main():
    url = 'https://movie.douban.com/top250'
    html = get_html(url)
    parse_html(html)


if __name__ == '__main__':
    main()

这是一个简单的爬取豆瓣电影Top250的代码,首先通过requests库获取网页的HTML代码,然后使用BeautifulSoup库解析HTML代码,获取电影名称和评分。

但是,这种单线程爬取的方式效率较低,因为在获取HTML代码的时候需要等待响应,而在等待响应的过程中CPU会空闲,无法充分利用计算机的性能。

2.多线程爬取

接下来,我们通过多线程的方式来优化爬取过程。首先,我们需要导入Python中的threading库:

import threading

然后,我们将获取HTML代码的代码放在一个函数中,并将其作为一个线程来运行:

def get_html(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except Exception as e:
        print(e)


class GetHtmlThread(threading.Thread):
    def __init__(self, url):
        threading.Thread.__init__(self)
        self.url = url

    def run(self):
        html = get_html(self.url)
        parse_html(html)

在上面的代码中,我们首先定义了一个GetHtmlThread类,继承自threading.Thread类,然后在类的构造函数中传入需要爬取的URL。在run方法中,我们调用get_html函数获取HTML代码,并将其传入parse_html函数中进行解析。

接下来,我们通过循环创建多个线程来进行爬取:

def main():
    urls = ['https://movie.douban.com/top250?start={}'.format(i) for i in range(0, 250, 25)]
    threads = []

    for url in urls:
        thread = GetHtmlThread(url)
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()

在上面的代码中,我们首先定义了一个urls列表,包含了所有需要爬取的URL。然后通过循环创建多个GetHtmlThread线程,并将其加入到threads列表中。最后,通过循环调用join方法等待所有线程执行完毕。

通过多线程的方式,我们可以充分利用计算机的性能,提高爬取效率。

3.线程池爬取

在多线程的方式中,我们需要手动创建和管理线程,这样会增加代码的复杂度。因此,我们可以使用Python中的线程池来进行优化。

首先,我们需要导入Python中的concurrent.futures库:

import concurrent.futures

然后,我们将获取HTML代码的代码放在一个函数中,并将其作为一个任务来提交给线程池:

def get_html(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except Exception as e:
        print(e)


def parse_html(html):
    soup = BeautifulSoup(html, 'lxml')
    movie_list = soup.find(class_='grid_view').find_all('li')

    for movie in movie_list:
        title = movie.find(class_='title').string
        rating = movie.find(class_='rating_num').string
        print(title, rating)


def main():
    urls = ['https://movie.douban.com/top250?start={}'.format(i) for i in range(0, 250, 25)]
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = [executor.submit(get_html, url) for url in urls]

    for future in concurrent.futures.as_completed(futures):
        html = future.result()
        parse_html(html)

在上面的代码中,我们首先定义了一个urls列表,包含了所有需要爬取的URL。然后通过with语句创建一个线程池,并设置最大线程数为5。接下来,我们通过循环将每个URL提交给线程池,并将返回的Future对象加入到futures列表中。最后,通过concurrent.futures.as_completed函数来等待所有任务执行完毕,并获取返回值进行解析。

通过线程池的方式,我们可以更加简洁地实现多线程爬取,并且可以更加灵活地控制线程的数量,避免线程过多导致系统负载过高的问题。

以上就是一文带你掌握Python中多线程和线程池的使用方法的详细内容,更多关于Python多线程 线程池的资料请关注脚本之家其它相关文章!

相关文章

  • windows下ipython的安装与使用详解

    windows下ipython的安装与使用详解

    大家都知道ipython是一个python的交互式shell,比默认的python shell好用得多,IPython有许多种安装方式,这主要和使用什么操作系统有关。本文给大家介绍的是在windows下ipython的安装与使用,有需要的朋友们可以参考学习。
    2016-10-10
  • Flask项目的部署的实现步骤

    Flask项目的部署的实现步骤

    本文主要介绍了Flask项目的部署的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • python+mongodb数据抓取详细介绍

    python+mongodb数据抓取详细介绍

    这篇文章主要介绍了python+mongodb数据抓取详细介绍,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • 能让Python提速超40倍的神器Cython详解

    能让Python提速超40倍的神器Cython详解

    今天带大家了解一下能让Python提速超40倍的神器,文章围绕着神器Cython展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • 七个生态系统核心库[python自学收藏]

    七个生态系统核心库[python自学收藏]

    无论你是想快速入手Python,还是想成为数据分析大神或者机器学习大佬,亦或者对Python代码进行优化,本文的python库都能为你提供一些帮助
    2021-08-08
  • 基于python神经卷积网络的人脸识别

    基于python神经卷积网络的人脸识别

    这篇文章主要为大家详细介绍了基于python神经卷积网络的人脸识别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • 配置 Pycharm 默认 Test runner 的图文教程

    配置 Pycharm 默认 Test runner 的图文教程

    今天小编就为大家分享一篇配置 Pycharm 默认 Test runner 的图文教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • 简介Python的collections模块中defaultdict类型的用法

    简介Python的collections模块中defaultdict类型的用法

    这里我们来简介Python的collections模块中defaultdict类型的用法,与内置的字典类最大的不同在于初始化上,一起来看一下:
    2016-07-07
  • pandas如何实现两个dataframe相减

    pandas如何实现两个dataframe相减

    这篇文章主要介绍了pandas如何实现两个dataframe相减方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 使用python+pygame实现中秋节动画效果

    使用python+pygame实现中秋节动画效果

    马上就要中秋节了,使用python可以实现中秋节动画效果,包括月亮、兔子和烟花吗?当然是可以的,那该如何实现呢?这篇文章我们主要使用pygame来实现,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-09-09

最新评论