python 包之 multiprocessing 多进程

yizhihongxing

Python 包之 multiprocessing 多进程

multiprocessing 是 Python 标准库中提供的模块,可以方便地使用多进程进行并发编程。它提供了与 Python 标准库 threading 模块相同的接口,但是使用多进程编程可以充分利用多核 CPU 的优势,用于加速 CPU 密集型任务。

multiprocessing 模块的主要组件

  • Process:进程对象,用于创建新进程。

  • Queue:进程间通信(IPC)的队列对象,用于在多个进程之间安全地共享数据。

  • Pool:进程池对象,用于管理池中的多个 Worker 进程,执行一组对数据集的并行操作。

  • LockRLockSemaphore:进程锁,用于控制多个进程对共享资源的访问。

创建新进程

multiprocessing.Process 可以用于创建新的进程,常用的方式有如下两种:

方式一:函数形式

import multiprocessing

def work(name):
    print(f"Working on {name}")

if __name__ == '__main__':
    p = multiprocessing.Process(target=work, args=('Alice',))
    p.start()
    p.join()

在上面的代码中,我们通过 multiprocessing.Process() 函数创建了一个新进程,并将 work() 函数作为任务传递给了该进程。start() 方法用于启动该进程,并且 join() 方法用于等待该进程完成。在运行该代码时,可以看到类似于如下输出:

Working on Alice

方式二:面向对象式

import multiprocessing

class Worker(multiprocessing.Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f"Working on {self.name}")

if __name__ == '__main__':
    p = Worker('Bob')
    p.start()
    p.join()

在上面的代码中,我们通过继承 multiprocessing.Process 类创建了一个新的进程对象,并覆盖了 run() 方法,该方法内部执行我们的工作。在运行该代码时,可以看到类似于如下输出:

Working on Bob

进程间通信

多个进程之间需要共享数据或结果时,可以使用 multiprocessing.Queue 类来实现进程间通信(IPC)。以下是一个示例,演示了两个进程之间如何实现数据的共享。

import multiprocessing

def producer(queue):
    for i in range(5):
        print(f'Producing {i}')
        queue.put(i)

def consumer(queue):
    while True:
        data = queue.get()
        if data is None:
            break
        print(f'Consuming {data}')

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=producer, args=(queue,))
    p2 = multiprocessing.Process(target=consumer, args=(queue,))
    p1.start()
    p2.start()
    p1.join()
    queue.put(None)
    p2.join()

在上面的代码中,我们创建了一个 multiprocessing.Queue 对象,并将其传递给了两个进程函数进行共享。producer 进程函数用于生成数据并将其放入队列中,consumer 进程函数负责不断地取出队列中的数据并进行消费。

在执行该代码时,可以看到类似于如下输出:

Producing 0
Consuming 0
Producing 1
Consuming 1
Producing 2
Consuming 2
Producing 3
Consuming 3
Producing 4
Consuming 4

进程池

multiprocessing.Pool 类可以用于创建一个进程池,执行一组对数据集的并行操作。以下是一个示例,演示了如何使用 Pool 实现对列表中数字的并行求平方。

import multiprocessing

def square(x):
    return x*x

if __name__ == '__main__':
    pool = multiprocessing.Pool()
    result = pool.map(square, [1, 2, 3, 4, 5])
    print(result)

在上面的代码中,我们创建了一个进程池,并使用 map() 方法实现对列表中数字的并行求平方。在运行该代码时,可以看到如下输出:

[1, 4, 9, 16, 25]

另外一个示例,演示了如何使用 Pool 实现对多个文件的并行读取和处理。

import multiprocessing
import os

def count_lines(filename):
    with open(filename, 'r') as f:
        lines = f.readlines()
    return len(lines)

if __name__ == '__main__':
    pool = multiprocessing.Pool()
    folder_path = './files'
    filenames = [os.path.join(folder_path, f) for f in os.listdir(folder_path)]
    results = pool.map(count_lines, filenames)
    total_lines = sum(results)
    print(f'Total number of lines in {len(filenames)} files: {total_lines}')

在上面的代码中,我们创建了一个进程池,并使用 map() 方法实现对多个文件的并行读取和处理。其中,count_lines() 函数用于读取文件并返回其行数。在运行该代码时,需要先准备好指定路径下的多个文件,然后可以看到如下输出:

Total number of lines in 3 files: 15

进程锁

在多个进程共享同一份数据时,可能会出现多个进程同时读写该数据的情况,如果没有加锁保护,可能会导致数据的错误和不可预期的结果。可以使用 multiprocessing.Lockmultiprocessing.RLockmultiprocessing.Semaphore 等类来实现进程锁的功能。

以下是一个示例,演示了如何使用 Lock 类来保证多个进程安全地访问同一份数据。

import multiprocessing

def deposit(balance, lock):
    for i in range(10000):
        lock.acquire()
        balance.value += 1
        lock.release()

def withdraw(balance, lock):
    for i in range(10000):
        lock.acquire()
        balance.value -= 1
        lock.release()

if __name__ == '__main__':
    balance = multiprocessing.Value('i', 0)
    lock = multiprocessing.Lock()

    d = multiprocessing.Process(target=deposit, args=(balance, lock))
    w = multiprocessing.Process(target=withdraw, args=(balance, lock))

    d.start()
    w.start()
    d.join()
    w.join()

    print(balance.value)

在上面的代码中,我们创建了一个共享变量 balance,并分别创建了存款和取款两个进程,它们会在 10000 次循环中反复对 balance 进行加减操作。为了避免多个进程同时访问同一份数据,我们使用 multiprocessing.Lock 类来对访问 balance 的进程进行加锁保护。在运行该代码时,可以看到如下输出:

0

可以看到,经过了 20000 次加减操作,最终 balance 的值保持不变,证明了我们的加锁保护起了作用。

总结

在本篇文章中,我们介绍了 Python 标准库 multiprocessing 模块的主要组件,包括创建新进程、进程间通信、进程池、进程锁等。同时,我们也给出了多个示例,演示了如何使用 multiprocessing 进行并发编程的实际应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python 包之 multiprocessing 多进程 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • python怎么提高计算速度

    要想提高Python的计算速度,通常可以采用以下几种方式: 1. 使用NumPy NumPy是Python一个常用的高性能科学计算库,它广泛地应用于各种科学计算中,能够提升计算速度。它的优势在于其基于C语言写的底层代码,很大程度上避免了Python解释器的运算速度瓶颈。 例如,假设我们需要求两个数组(x和y)的点积结果,如果使用Python自带的列表进行计算…

    python 2023年6月3日
    00
  • python随机生成大小写字母数字混合密码(仅20行代码)

    下面我就详细讲解一下“Python随机生成大小写字母数字混合密码(仅20行代码)”的完整攻略。 介绍 该Python程序可以随机生成由大小写字母和数字组成的密码。该程序只需20行代码,简单易懂,适用于初学者学习和使用。程序共分为3个部分,分别为导入Python内置模块,定义函数,生成密码。 步骤 导入Python内置模块 我们可以通过Python中内置模块r…

    python 2023年6月3日
    00
  • python multiprocessing多进程变量共享与加锁的实现

    下面我来详细讲解一下“python multiprocessing多进程变量共享与加锁的实现”的完整攻略。 简介 Python 的 multiprocessing 模块提供了一种使用多进程并行处理数据的方法,可以显著提高数据处理的速度。不过在多进程编程中,每个进程独立运行,各自维护着自己的内存空间,因此共享变量需要特别处理,否则容易出现多个进程并发修改同一个…

    python 2023年6月6日
    00
  • Python自定义线程类简单示例

    Python自定义线程类是指通过继承Python内置的threading.Thread类来创建自己的线程类,该方法可以比较方便地创建多线程应用程序。下面将给出一个简单的示例来解释如何创建自定义线程类。 创建自定义线程类 首先,我们需要导入threading模块,然后定义一个自定义线程类,例如: import threading class MyThread(…

    python 2023年6月6日
    00
  • python机器学习实现oneR算法(以鸢尾data为例)

    下面是详细讲解“Python机器学习实现oneR算法(以鸢尾data为例)”的完整攻略,包括算法原理、Python实现代码和两个示例说明。 算法原理 oneR算法是一种简单的分类算法,它通过统计每个特征的每个取值在不同类别中出现的频率,选择出现频率最高的特征和取值作为分类规则。具体来说,oneR算法的步骤如下: 对于每个特征统计每个取值在不同类别中出现的频率…

    python 2023年5月14日
    00
  • Python 匿名函数(lambda表达式)用法详解

    在 Python 中,匿名函数也被称为 lambda 函数。它是一种没有名称的函数,可以快速地创建简单的函数。 Python匿名函数语法 Python 中的 lambda 函数的语法是: lambda arguments: expression 其中,arguments 是函数的参数,expression 是函数执行的表达式。 Python匿名函数实例 la…

    2023年2月21日
    00
  • 浅谈Python中的全局锁(GIL)问题

    浅谈Python中的全局锁(GIL)问题 什么是GIL GIL 全称 Global Interpreter Lock,意为全局解释器锁。在 Python 中,一次只能执行一个线程,所以为了保证线程安全,引入了 GIL 的概念。GIL 是 Python 解释器中自带的机制,用来保证同一时刻只有一个线程在执行 Python 代码。当一个线程开始执行 Python…

    python 2023年5月19日
    00
  • 简单的抓取淘宝图片的Python爬虫

    下面我会介绍一下“简单的抓取淘宝图片的Python爬虫”的完整攻略。 攻略概述 抓取淘宝商品图片需要用到 Python 爬虫技术。爬虫的实现流程一般为: 根据淘宝商品链接,获取商品页面 HTML 源代码。 从 HTML 源代码中提取出图片链接。 根据图片链接,请求图片并保存到本地。 实现步骤 步骤1:获取商品页面 HTML 源代码 使用 requests 库…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部