前言

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

作者:东哥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. jquery-form详解

    jQuery-Form 概观 jQuery表单插件允许您轻松而不显眼地升级HTML表单以使用AJAX.主要方法ajaxForm和ajaxSubmit从表单元素收集信息以确定如何管理提交过程.这两种方法 ...

  2. Laravel 中自定义 手机号和身份证号验证

    首先在 Providers\AppServiceProvider.php 文件中自定义 手机号和身份证号验证 // AppServiceProvider.php 文件 <?php namespa ...

  3. MySQL高级用法

    -- 关联查询-- select * from Goods_BomItems s,Goods_Bom t where t.GoodsBomId = s.GoodsBomId and t.GoodsBo ...

  4. python实现从文件夹随机拷贝出指定数量文件到目标文件夹

    为了方便倒腾数据,功能如题,该脚本和操作目录在同一根目录 实际运行时要手动修改程序中:cpfile_rand('img', 'outfile', 10) # 操作目录,输出目录,输出数量 import ...

  5. jmeter跨线程组获取cookie或jmeter线程组共享cookie-笔者亲测

    一.Jmeter版本 此次示例采用的是apache-jmeter-5.2.1版本 二.设置配置文件使Cookie管理器保存cookie信息. 修改apache-jmeter-5.2.1/bin/jme ...

  6. iview表单验证--数字必填+校验

    直接使用: { required: true, type:"integer", message:"请填写整数", trigger: "blur&quo ...

  7. elasticsearch7.6 安装 并且开启外网访问,真的好累。

    下载 下载页面 https://www.elastic.co/cn/downloads/elasticsearch wget https://artifacts.elastic.co/download ...

  8. 网页不让用户复制方法总汇,设置html禁止选择,保护源码,js禁止复制文字

    这篇文章主要讲解:右键复制失效方法.菜单"文件"-"另存为"失效方法.防止查看源代码进行复制的方法.防止页面缓存的方法.来达到一定的代码保护效果 右键复制失效方 ...

  9. 隐写工具outguess安装使用介绍

      0x00 outguess下载安装 Kail终端命令输入git clone https://github.com/crorvick/outguess 安装包随即下载到文件夹.双击打开文件夹,右键点 ...

  10. 【Nginx】如何获取客户端真实IP、域名、协议、端口?看这一篇就够了!

    写在前面 Nginx最为最受欢迎的反向代理和负载均衡服务器,被广泛的应用于互联网项目中.这不仅仅是因为Nginx本身比较轻量,更多的是得益于Nginx的高性能特性,以及支持插件化开发,为此,很多开发者 ...