前言

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。

作者:东哥IT笔记

现在很多CPU都支持多核,甚至是手机都已经开始支持多核了。而Python的GIL(Global Interpreter Locko)则使得其没法使用这些多核带来的优势。还好从Python2.6开始,引入了multiprocessing模块,我们终于可以使用多核带来的便利了。

本文,你会学习到下面这些内容:

  • 使用多进程的优点
  • 使用多进程的缺点
  • 使用multiprocessing来创建多进程
  • Process的子类化
  • 创建进程池

本文并不是一个multiprocessing的全面的介绍,假如你想全面的了解它,可以参见官方的文档:

https://docs.python.org/2/library/multiprocessing.html

下面让我们开始吧!

使用多进程的优点

使用多进程有很多优点:

  • 多进程使用独立的内存空间
  • 相比于线程,代码更加直观
  • 能够使用多个CPU/多核
  • 避免GIL
  • 子进程可以被kill(和thread不同)
  • multiprocessing有和threading.Thread类似的接口
  • 对CPU绑定的进程比较好(加密,二进制搜索,矩阵乘法等)

下面我们来看看使用多进程有什么缺点:

使用多进程的缺点

使用多进程也有一些缺点:

  • 进程间通信更加复杂
  • 内存的占用大于线程

使用multiprocessing来创建进程

multiprocessing是用来模拟threading.Thread类工作的。下面就是一个使用它的例子:

import multiprocessing
import random
import time def worker(name: str) -> None:
print(f'Started worker {name}')
worker_time = random.choice(range(1, 5))
time.sleep(worker_time)
print(f'{name} worker finished in {worker_time} seconds') if __name__ == '__main__':
processes = []
for i in range(5):
process = multiprocessing.Process(target=worker,
args=(f'computer_{i}',))
processes.append(process)
process.start() for proc in processes:
proc.join()

首先第一步需要import multiprocessing模块,另外两个import分别是为random和time服务的。

worker函数就是用来假装做一些事情,传入一个name的参数,没有什么返回,他首先打印name的值,然后随机sleep一段时间用来模拟做一段很长时间的工作,最后打印work finish。

紧接着,你使用multiprocessing.Process创建了5个进程,他的使用和threading.Tread()比较类似,你告诉Process哪个目标函数需要调用,以及会传入什么参数给他们,然后你调用了start函数来启动进程。另外你会把这些进程加入到一个list中。

最后,你遍历这个list,调用join方法,这个方法其实就是告诉Python等到进程结束。

假如你run这个函数,你会看到类似下面这样的输出:

其实你每次运行这个函数,结果都会有稍许的不同,主要还是因为你调用了random函数,你可以试试,看看你自己的输出。

Process的子类化

multiporcessing模块中的Process类是可以子类化的,他和threading.thread的类差不多。我们来看下面代码:

# worker_thread_subclass.py
import random
import multiprocessing
import time
class WorkerProcess(multiprocessing.Process):
def __init__(self, name):
multiprocessing.Process.__init__(self)
self.name = name
def run(self):
"""
Run the thread
"""
worker(self.name)
def worker(name: str) -> None:
print(f'Started worker {name}')
worker_time = random.choice(range(1, 5))
time.sleep(worker_time)
print(f'{name} worker finished in {worker_time} seconds')
if __name__ == '__main__':
processes = []
for i in range(5):
process = WorkerProcess(name=f'computer_{i}')
processes.append(process)
process.start()
for process in processes:
process.join()

这里,我们写了一个multiprocess.Process()的子类,并且重写了run()方法。

其他方面和上面的例子其实是类似的,现在我们可以来看看具体的输出,和上面的也类似。

创建一个进程池

假如你有很多进程需要运行,有时你希望能够限制进程运行的数目。比如说,你需要运行20个进程,但是你只有4个核,那么你可以使用multiprocessing模块来创建一个进程池,用它来限制每次进程运行的数目到4个。

下面是示例的代码:

import random
import time
from multiprocessing import Pool
def worker(name: str) -> None:
print(f'Started worker {name}')
worker_time = random.choice(range(1, 5))
time.sleep(worker_time)
print(f'{name} worker finished in {worker_time} seconds')
if __name__ == '__main__':
process_names = [f'computer_{i}' for i in range(15)]
pool = Pool(processes=5)
pool.map(worker, process_names)
pool.terminate()

这个例子中,worker函数还是一样的,主要是后面的代码, 我们创建了一个进程池,它的数目是5,也就意味着最大的运行数目是5。使用这个pool,你需要调用map()方法,然后把你需要的调用的方法和参数传递给他。

这样的话,Python每次只会使用5个进程来运行直到结束。最后你需要调用terminate()函数,否则你会发现下面的错误:

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/resource_tracker.py:216:

UserWarning: resource_tracker: There appear to be 6 leaked semaphore objects to clean up at shutdown

这个代码的具体输出如下所示:

Python基础知识点:多进程的应用讲解的更多相关文章

  1. 最全Python基础知识点梳理

    本文主要介绍一些平时经常会用到的python基础知识点,用于加深印象,也算是对于学习这门语言的一个总结与回顾.python的详细语法介绍可以查看官方编程手册,也有一些在线网站可以学习 python语言 ...

  2. Python基础知识点小结

    1.Python基础知识 在Python中的两种注释方法,分别是#注释和引号('''   ''')注释,#注释类似于C语言中的//注释,引号注释类似于C语言中的/*   */注释.接着在Python中 ...

  3. Python基础知识点总结

    Python基础知识与常用数据类型 一.Python概述: 1.1.Python的特点: 1.Python是一门面向对象的语言,在Python中一切皆对象 2.Python是一门解释性语言 3.Pyt ...

  4. python基础知识点四

    网络编程(socket) 软件开发的架构: 两个程序之间通讯的应用大致通过从用户层面可以分为两种: 1是C/S,即客户端与服务端,为应用类的,比如微信,网盘等需要安装桌面应用的 2是B/S,即浏览器与 ...

  5. python基础知识点三

    内置函数和匿名函数 python 一共有68个内置的函数:它们就是python提供给你直接可以拿来使用的所有函数 内置函数的图:链接 :https://www.processon.com/mindma ...

  6. python 基础知识点整理 和详细应用

    Python教程 Python是一种简单易学,功能强大的编程语言.它包含了高效的高级数据结构和简单而有效的方法,面向对象编程.Python优雅的语法,动态类型,以及它天然的解释能力,使其成为理想的语言 ...

  7. Python基础知识点

    自学记录: 1.字符串 python中单引号和双引号使用完全相同. 使用三引号('''或""")可以指定一个多行字符串. 转义符 '\' 反斜杠可以用来转义,使用r可以让 ...

  8. python 基础知识点二

    深浅copy 1对于赋值运算来说,l1与l2指向的是同一个内存地址,所以他们是完全一样的. l1 = [1,2,3,['barry','alex']] l2 = l1 l1[0] = 111 prin ...

  9. python 基础知识点一

    基础数据类型初始. 数字:int 12,3,45 + - * / **    int: bit_lenth()转化为2进制的最小位数. % 取余数 ps:type() 字符串转化成数字:int(str ...

随机推荐

  1. TCP实战二(半连接队列、全连接队列)

    TCP实验一我们利用了tcpdump以及Wireshark对TCP三次握手.四次挥手.流量控制做了深入的分析,今天就让我们一同深入理解TCP三次握手中两个重要的结构:半连接队列.全连接队列. 参考文献 ...

  2. postman使用小结(一)

    postman可以用来做接口测试. 下面是使用的基本步骤: 1新建http请求: 2设置请求类型get/post/put/delete...: 3设置请求的url: 4设置请求的Header头部信息, ...

  3. mybatis源码配置文件解析之五:解析mappers标签流程图

    前面几篇博客分析了mybatis解析mappers标签的过程,主要分为解析package和mapper子标签.补充一张解析的总体过程流程图,画的不好,多多谅解,感谢.

  4. 无题II HDU - 2236 【二分图+二分答案】

    题目 这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小. Input 输入一个整数T表示T组数据. 对于每组数据第一行输入一 ...

  5. python之浅谈循环

    目录 流程控制之while循环 语法 while+break while+continue while+else while循环的嵌套 流程控制之for循环 语法 for+break for+cont ...

  6. ADAS感知设计

    ADAS传感器融合 0.传感器标定 首先标定传感器.一般可以精度高的传感标定用精度低一个数量级的传感器,如用激光雷达标定毫米波雷达. 毫米波雷达标定:可以采用激光雷达对毫米波雷达进行标定.选取一个纹理 ...

  7. 深入了解JVM-方法区

    本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: 深入了解JVM-方法区 当JVM使用类装载器装载某个类时,它首先要定位对应的class文件,然后读入这个class文件,最 ...

  8. iOS应用千万级架构开篇

    一款好的APP架构,是需要适应复杂的业务场景的.当然它也是可以监控的,比如性能.卡顿等.你写的每一行代码,测试都可以查看到,并测试覆盖到. 一直很想分享一下,一个大型的APP都做了些什么事情,这些事情 ...

  9. DP没入门就入土

    写在前面 记录最近刷的DP题 以及 打死都不可能想到状态设计DP系列 汇总 洛谷 P6082 [JSOI2015]salesman 树形\(\texttt{DP}\) + 优先队列 比较容易看出来这是 ...

  10. JS数组与对象赋值问题

    在W3C的在线编程中经过测试发现以下问题: 当一个数组内部元素为对象时,给数组赋值应该先给对象赋值,然后把该对象push到数组中. 如下所示: 在控制台打印之后的数据格式为下图所示: 如果在给数组赋值 ...