Python -- 多进程

Python中多进程在爬虫中的使用 如何利用多进程的方法来提高Python爬虫的速度和效率。介绍了multiprocessing库的使用,并且用验证爬到的代理IP可用性作为例子来讲述多进程方法的具体使用。 阅读详情

  • 由于Python的GIL全局解释器锁存在,多线程未必是CPU密集型程序的好的选择
  • 多进程可以完全独立的进程环境中运行程序,可以较充分地利用多处理器
  • 但是进程本身的隔离带来的数据不共享也是一个问题。而且线程比进程轻量级

multiprocessing

Process类

  • Process类遵循了Thread类的API
import multiprocessing
import datetime

def calc(i):
    sum = 0
    for _ in range(1000000000): # 10亿
        sum += 1
    return i, sum

if __name__ == '__main__':
    start = datetime.datetime.now()

    ps = []
    for i in range(4):
        p = multiprocessing.Process(target=calc, args=(i,), name='calc-{}'.format())
        ps.append(p)
        p.start()

    for p in ps:
        p.join()
        print(p.name, p.exitcode)

    delta = (datetime.datetime.now() - start).total_seconds()
    print(delta)
    print('===end===')

对于上面这个程序,在同一主机上运行时长的对比

  • 使用单线程、多线程跑了4分钟多
  • 多进程用了1分半
    看到了多个进程都在使用CPU,这是真并行

注意

多进程代码一定要放在__name__ == "__main__"下面执行

名称说明
pid进程id
exitcode进程的退出状态码
terminate()终止指定的进程

进程间同步

  • Python在进程间同步提供了和线程同步一样的类,使用的方法一样,使用的效果也类似
  • 不过,进程间代价要高于线程间,而且系统底层实现是不同的,只不过Python屏蔽了这些不同之处,让用户简单使用多进程
  • multiprocessing还提供共享内存、服务器进程来共享数据,还提供了用于进程间通讯的Queue队列、Pipe管道
  • 通信方式不同
    1. 多进程就是启动多个解释器进程,进程间通信必须序列化、反序列化
    2. 数据的线程安全性问题
      如果每个进程中没有实现多线程,GIL可以说没什么用了

进程池举例

  • multiprocessing.Pool 是进程池类
名称说明
apply(self, func, args=(), kwds={})阻塞执行,导致主进程执行其他子进程就像一个个执行
apply_async(self, func, args=(), kwds={}, callback=None, error_callback=None)与apply方法用法一致,非阻塞异步执行,得到结果后会执行回调
close()关闭池,池不能再接受新的任务,所有任务完成后退出进程
terminate()立即结束工作进程,不再处理未处理的任务
join()主进程阻塞等待子进程的退出, join方法要在close或terminate之后使用

同步调用

  • pool.apply 同步阻塞的方法,多进程串行
import logging
import datetime
import multiprocessing

# 日志打印进行id、进程名、线程id、线程名
logging.basicConfig(level=logging.INFO,
                    format="%(process)d %(processName)s %(thread)d %(message)s")

def calc(i):
    sum = 0
    for _ in range(1000000000): # 10亿
        sum += 1
    logging.info(sum)
    return i, sum # 进程要return,才可以拿到这个结果

if __name__ == '__main__':
    start = datetime.datetime.now()

    pool = multiprocessing.Pool(4)
    for i in range(4):
        # 返回值,同步调用,注意观察CPU使用
        ret = pool.apply(calc, args=(i,))
        print(ret)
    pool.close()
    pool.join()

    delta = (datetime.datetime.now() - start).total_seconds()
    print(delta)
    print('===end===')
  • 执行结果
333980 SpawnPoolWorker-1 332164 1000000000
(0, 1000000000)
(1, 1000000000)
332272 SpawnPoolWorker-3 332200 1000000000
(2, 1000000000)
334224 SpawnPoolWorker-4 324984 1000000000
332264 SpawnPoolWorker-2 332232 1000000000
(3, 1000000000)
483.274714
===end===
  • cup使用情况,4个进程串行处理
    在这里插入图片描述

异步调用

  • pool.aaply_async 异步非阻塞,真并行
import logging
import datetime
import multiprocessing

# 日志打印进行id、进程名、线程id、线程名
logging.basicConfig(level=logging.INFO,
                    format="%(process)d %(processName)s %(thread)d %(message)s")

def calc(i):
    sum = 0
    for _ in range(1000000000): # 10亿
        sum += 1
    logging.info(sum)
    return i, sum # 进程要return,callback才可以拿到这个结果

if __name__ == '__main__':
    start = datetime.datetime.now()

    pool = multiprocessing.Pool(4)
    for i in range(4):
        # 异步拿到的返回值是什么,回调起了什么作用
        ret = pool.apply_async(
            calc, args=(i,),callback=lambda ret: logging.info('{} in callback'.format(ret)))

        print(ret, '~~~~~~~')
    pool.close()
    pool.join()

    delta = (datetime.datetime.now() - start).total_seconds()
    print(delta)
    print('===end===')
  • 执行结果
<multiprocessing.pool.ApplyResult object at 0x0000015814F616D8> ~~~~~~~
<multiprocessing.pool.ApplyResult object at 0x0000015814F61780> ~~~~~~~
<multiprocessing.pool.ApplyResult object at 0x0000015814F618D0> ~~~~~~~
<multiprocessing.pool.ApplyResult object at 0x0000015814F61978> ~~~~~~~
335068 SpawnPoolWorker-4 208444 1000000000
334080 MainProcess 335552 (2, 1000000000) in callback
332176 SpawnPoolWorker-2 334620 1000000000
334080 MainProcess 335552 (1, 1000000000) in callback
328432 SpawnPoolWorker-1 335124 1000000000
334080 MainProcess 335552 (0, 1000000000) in callback
334840 SpawnPoolWorker-3 335532 1000000000
334080 MainProcess 335552 (3, 1000000000) in callback
204.866947
===end===
  • cpu运行情况,4个进程并行处理
    在这里插入图片描述

多进程、多线程的选择

  1. CPU密集型
    CPython中使用到了GIL,多线程的时候锁相互竞争,且多核优势不能发挥,选用Python多进程效率更高
  2. IP密集型
    在Python中适合是用多线程,可以减少多进程间IO的序列化开销。且在IO等待的时候,切换到其他线程继续执行,效率不错

应用

请求/应答模型:WEB应用中常见的处理模型

  • master启动多个worker工作进程,一般和CPU数目相同。发挥多核优势
  • worker工作进程中,往往需要操作网络IO和磁盘IO,启动多线程,提高并发处理能力。worker处理用户的请求,往往需要等待数据,处理完请求还要通过网络IO返回响应
  • 这就是nginx工作模式
python多进程编程 python中的多进程,多进程的创建,进程之间的通信,进程执行结果 阅读详情

相关推荐

Windows上的Python多进程

Python Multiprocessing on Windows 因为众所周知的GIL(全局解释器锁),在Python上实现真正的并发只能通过python multiprocessing。但是在Windows上,运用python multiprocessing并没有在Linux那么简单。 if __name__ == "__main__": 也许大家有些在Linux跑的很好的多进程的程序,在Windows上一跑就会经常遇到这些错误的信息 “An attempt has been made to start

qq_43051923的博客 2353

Python多进程代码示例

Python多进程代码示例

Ghjkku的博客 13万+

用Unity Wheel Collider做坦克转向?3步实现履带式载具物理效果

本文详细解析了如何利用Unity的Wheel Collider组件实现履带式载具的差速转向物理效果。通过思维转换、场景搭建和核心代码实现三步,将Wheel Collider从模拟轮式车辆转向改造为控制履带扭矩差的系统,并深入探讨了参数调试与真实感提升的方法,帮助开发者打造物理反馈扎实的坦克或特种车辆模拟。

weixin_29009971的博客 222

Python多进程详解

Python多进程的详细教程

ifhuke的博客 7010

别再为GEE注册发愁了!用谷歌Cloud Project,5分钟搞定谷歌地球引擎账户(保姆级图文)

本文提供2024最新版谷歌地球引擎(GEE)账户注册的保姆级教程,通过谷歌Cloud Project快速完成注册,5分钟极速通关。详细解析注册前的准备、分步图解流程、常见误区及解决方案,帮助用户避开90%的注册陷阱,直达GEE核心功能区。

weixin_42557830的博客 199

三极管开关电路在脉冲应用中的性能瓶颈分析

深入探讨三极管开关电路在高频脉冲场景下的响应延迟与功耗问题,揭示其性能限制的关键因素。结合实际应用,分析开关速度与信号完整性之间的矛盾,为优化三极管开关电路设计提供实用参考。

weixin_42602368的博客 587

Python并发之多进程

要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识。Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()

上善若泪 5118

RYU+mininet——RYU

1. 使用RYU做mininet的控制器 1.1 RYU介绍与安装 RYU是一款基于python的控制器,你可用Ryu实现各种想要实现的网络功能,它可以下发或接收流表进行各种路由运算。 建议使用高版本的Ubuntu系统安装ryu,否则会有各种错误,安装过程比较简单,如下: apt install gcc libffi-dev libssl-dev libxml2-dev libxslt1-...

qq_34415266的博客 1万+

(python)多进程

工作中遇到任务较重且耗时相对较长的情况,这时候想起来用多进程处理这类IO 密集型任务.最重要的是,multiprocessing.Pool实在是简单又高效,充分利用了多核CPU同时并行处理多个任务.支持多进程并行处理,可以利用多核 CPU 提高任务的执行效率和速度。提供了简单易用的 API,方便进行任务的分发和结果的收集,代码编写相对简单。可以在一定程度上降低代码复杂度,例如避免手动创建和管理多个进程等。缺点:进程切换开销较大,特别是当进程池中进程数量过多时,容易产生性能瓶颈。

MARST.ZHANG的博客 4395

在macOS上使用GitHub的超详细指南

GitHub:免费的远程仓库,可用来托管自己的开源项目。它利用了Git强大的克隆和分支功能,让我们参与别人的开源项目和让别人参与自己的开源项目变得简单高效。

Mars的博客 3391

YOLOv11 损失函数解析

YOLOv11 在 YOLO 系列的持续演进中,通过 ​多模态损失协同优化、动态任务感知机制 和 ​超轻量化设计,实现了检测精度与推理效率的再突破。其损失函数设计融合了前沿的几何建模、分布学习与自监督技术,显著提升了复杂场景下的鲁棒性。

浩瀚之水的专栏 6702

Python中的多进程(一看就懂)

python中的多进程(简单易懂版)

Elon15的博客 9907

PyTorch实战(2)——使用PyTorch构建神经网络

在本节中,我们使用 PyTorch 在简单数据集上构建了一个神经网络,训练神经网络来映射输入和输出,并通过执行反向传播来更新权重值以最小化损失值,并利用 Sequential 类简化网络构建过程;介绍了获取网络中间值的常用方法,以及如何使用 save、load 方法保存和加载模型,以避免再次训练模型。

盼小辉丶的博客 1万+

Python多进程

单进程示例 举例一个吃饭活动,有一碗汤和一碗饭,正常操作是一口饭一口汤(当然你先把汤或者饭一口气吃完,当我无话可说)。单进程只能是先吃完饭,再喝汤;或者是先喝完汤,再吃饭。 看代码 import time def drink(): for i in range(3): print("喝汤……") time.sleep(1) def eat(): for i in range(3): print("吃饭……") time

帅帅气气的黑猫警长 4万+

Calibre:LVS 快速debug short/open技巧

用Fix Suggestion和Short Isolate两种方法debug LVS问题

m0_61544122的博客 7455

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Python 多进程好很多

摘要:Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用g

Teman的博客 5263

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【Python】Python多进程详解

进程(Process),顾名思义,就是进行中的程序。有一句话说得好:程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体。进程是资源分配的最小单元,也就是说每个进程都有其单独的内存空间。Unix/Linux系统通过fork系统调用创建一个进程,但是在Windows中并没有fork调用。但是别担心,Python中内置的multiprocessing模块是跨平台的,我们可以通过对multiprocess模块中的Process类进行实例化创建一个进程对象,如: 执行结果如下: 创建一个子

m0_59162248的博客 7198

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

【Python】多进程

进程(Process),顾名思义,就是进行中的程序。进程是python中最小的资源分配单元,进程之间的数据,内存是不共享的,每启动一个进程,都要独立分配资源和拷贝访问的数据,所以进程的启动和销毁的代价是比较大。Python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以多个线程,每条线程并行执行不同的任务。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

【Python】python中多进程处理

python中多进程相关简单介绍

sinat_41752325的博客 2958

python实现多进程

在这里用Python程序来实现多进程并加深对多进程并发的理解

u014556057的专栏 3万+

Python多进程学习及实现多进程版文件复制器

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。程序是固定不变的,而进程会根据运行需要,让操作系统动态分配各种资源。另外,CPU的时间片轮转就是在切换执行不同的进程,但进程切换比较浪费时间,就引进了轻量级进程,也就是所谓的线程,一个进程包括多个线程。

2401_82928104的博客 2075

python多进程,python multiprocessing 多进程使用方法

python多进程使用,python multiprocessing使用方法

村中少年的专栏 2070

python多进程的理解,多进程读写公共数据,多进程并行,

1. 多进程读写公共数据,多进程并行 #公共数据 temp = np.zeros((4,12)) # 回调函数,用于多进程读写公共数据的,我的理解:多进程在回调函数这里是串行的,否则同时读写会乱掉 # 回调函数必须只有一个输入参数 def mycallback(index): i,j = index[0],index[1] temp[i,j] = i+j # 多进程处理的耗时的算法...

weixin_41457494的博客 1710

python多进程反而慢_python 多进程使用总结

python中的多进程主要使用到multiprocessing 这个库。这个库在使用 multiprocessing.Manager().Queue时会出问题,建议大家升级到高版本python,如2.7.11,可具体参考《python版本升级》。python使用线程池可参考《python线程池实现》一、多进程使用1、linux下可使用 fork 函数#!/bin/env pythonimport...

weixin_39535557的博客 1733
上一篇: Python -- 数据结构和GIL全局解释器锁
下一篇: Linux中的特殊进程
鹿夏
博客等级 码龄8年 24粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值