python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录。

系列文章

fork()

import os
pid = os.fork() # 创建一个子进程
if pid == 0:
print('这是子进程')
print(os.getpid(),os.getppid())
else:
print('这是父进程')
print(os.getpid())
os.wait() # 等待子进程结束释放资源
  • fork函数被调用后会返回两次,pid为0的代表子进程,其他返回子进程的id号表示父进程。

  • getpid和getppid函数可以获取本进程和父进程的id号;

fork方式的缺点:

  1. 兼容性差,只能在类linux系统下使用,windows系统不可使用;
  2. 扩展性差,当需要多条进程的时候,进程管理变得很复杂;
  3. 会产生“孤儿”进程和“僵尸”进程,需要手动回收资源。

优点:

是系统自带的接近低层的创建方式,运行效率高。

Process创建进程

  • 创建方式一:
from multiprocessing import Queue, Process
import os
def test():
time.sleep(2)
print('this is process {}'.format(os.getpid())) if __name__ == '__main__':
p = Process(target=test)
p.start() # 子进程 开始执行
p.join() # 等待子进程结束
print('ths peocess is ended')
  • 创建方式二:
from multiprocessing import Queue, Process
import os
class MyProcess(Process): def run(self):
time.sleep(2)
print('this is process {}'.format(os.getpid())) def __del__(self):
print('del the process {}'.format(os.getpid())) if __name__ == '__main__':
p = MyProcess()
p.start()
print('ths process is ended')
# 结果:
ths process is ended
this is process 7600
del the process 7600
del the process 12304

说明:

  • Process对象可以创建进程,但Process对象不是进程,其删除与否与系统资源是否被回收没有直接的关系。

  • 上例看到del方法被调用了两次,Process进程创建时,子进程会将主进程的Process对象完全复制一份,这样在主进程和子进程各有一个Process对象,但是p1.start()启动的是子进程,主进程中的Process对象作为一个静态对象存在。

  • 主进程执行完毕后会默认等待子进程结束后回收资源,不需要手动回收资源;

  • join()函数用来控制子进程结束的顺序,主进程会阻塞等待子进程结束,其内部也有一个清除僵尸进程的函数,可以回收资源;

  • 当子进程执行完毕后,会产生一个僵尸进程,其会被join函数回收,或者再有一条进程开启,start函数也会回收僵尸进程,所以不一定需要写join函数。

  • windows系统在子进程结束后会立即自动清除子进程的Process对象,而linux系统子进程的Process对象如果没有join函数和start函数的话会在主进程结束后统一清除。

Process对象分析

class Process(object):
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
pass
# Process对象是python用来创建进程的类
group:扩展保留字段;
target:目标代码,一般是我们需要创建进程执行的目标函数。
name:进程的名字,如果不指定会自动分配一个;
args:目标函数的普通参数;
kwargs:目标函数的键值对参数; # 方法
start():创建一个子进程并执行,该方法一个Process实例只能执行一次,其会创建一个进程执行该类的run方法。
run():子进程需要执行的代码;
join():主进程阻塞等待子进程直到子进程结束才继续执行,可以设置等待超时时间timeout.
terminate():使活着的进程终止;
is_alive():判断子进程是否还活着。

进程池Pool

如果需要创建大量的进程,就需要使用Pool了。

from multiprocessing import Queue, Process, Pool
import os
def test():
time.sleep(2)
print('this is process {}'.format(os.getpid())) def get_pool(n=5):
p = Pool(n) # 设置进程池的大小
for i in range(10):
p.apply_async(test)
p.close() # 关闭进程池
p.join() if __name__ == '__main__':
get_pool()
print('ths process is ended')

分析:

  • 如上,进程池Pool被创建出来后,即使实际需要创建的进程数远远大于进程池的最大上限,p1.apply_async(test)代码依旧会不停的执行,并不会停下等待;相当于向进程池提交了10个请求,会被放到一个队列中;

  • 当执行完p1 = Pool(5)这条代码后,5条进程已经被创建出来了,只是还没有为他们各自分配任务,也就是说,无论有多少任务,实际的进程数只有5条,计算机每次最多5条进程并行。

  • 当Pool中有进程任务执行完毕后,这条进程资源会被释放,pool会按先进先出的原则取出一个新的请求给空闲的进程继续执行;

  • 当Pool所有的进程任务完成后,会产生5个僵尸进程,如果主线程不结束,系统不会自动回收资源,需要调用join函数去回收。

  • join函数是主进程等待子进程结束回收系统资源的,如果没有join,主程序退出后不管子进程有没有结束都会被强制杀死;

  • 创建Pool池时,如果不指定进程最大数量,默认创建的进程数为系统的内核数量.

Pool对象分析

class Pool(object):
def __init__(self, processes=None, initializer=None, initargs=(),
maxtasksperchild=None, context=None):
pass
# 初始化参数
processes:进程池的大小,默认cpu内核的数量
initializer:创建进程执行的目标函数,其会按照进程池的大小创建相应个数的进程;
initargs:目标函数的参数
context:代码的上下文 # 方法
apply():使用阻塞方式调用func;
apply_async():使用非阻塞方式条用func;
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出,必须在close()后面使用;
map(self, func, iterable, chunksize=None):多进程执行一个函数,传入不同的参数;
starmap(self, func, iterable, chunksize=None):和map类似,但iterable参数可解压缩;
starmap_async(self, func, iterable, chunksize=None, callback=None,error_callback=None):使用异步的方式的starmap,callback为返回后的处理函数
map_async(self, func, iterable, chunksize=None, callback=None,error_callback=None):异步方式的map
  • 实例
from multiprocessing import Pool
import os
def test(n):
time.sleep(1)
print('this is process {}'.format(os.getpid()))
return n def test1(n, m):
print(n, m)
print('this is process {}'.format(os.getpid())) def back_func(values): # 多进程执行完毕会返回所有的结果的列表
print(values) def back_func_err(values): # 多进程执行完毕会返回所有错误的列表
print(values) def get_pool(n=5):
p = Pool(n)
# p.map(test, (i for i in range(10))) # 阻塞式多进程执行
# p.starmap(test1, zip([1,2,3],[3,4,5])) # 阻塞式多进程执行多参数函数
# 异步多进程执行函数
p.map_async(test, (i for i in range(5)), callback=back_func, error_callback=back_func_err)
# 异步多进程执行多参数函数
p.starmap_async(test1, zip([1,2,3],[3,4,5]), callback=back_func, error_callback=back_func_err)
print('-----')
p.close()
p.join() if __name__ == '__main__':
get_pool()
print('ths process is ended')

进程锁

进程虽然不像线程那样共享内存的数据,而是每个进程有单独的内存,但多进程也是共享文件系统的,即硬盘系统;当多进程同时写入文件操作时,可能造成数据的破坏,因此进程也存在同步锁。

from multiprocessing import Pool, Lock
muex = Lock() def test():
if muex.acquire():
f = open('./test_pro.txt', 'r+', encoding='utf-8')
x = f.read()
if not x:
f.write('0')
else:
f.seek(0)
f.write(str(int(x)+1))
f.close()
muex.release() if __name__ == '__main__':
p = Pool(5)
for i in range(10):
p.apply_async(test)
p.close()
p.join()
with open('./test_pro.txt', 'r+', encoding='utf-8') as f:
print(f.read())

进程锁可以保证文件系统的安全,但是它使得并行变成了串行,效率下降了,也可能造成死锁问题,一般避免用锁机制。

python并发编程之multiprocessing进程(二)的更多相关文章

  1. python并发编程之Queue线程、进程、协程通信(五)

    单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ...

  2. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  3. python并发编程之asyncio协程(三)

    协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...

  4. python并发编程之threading线程(一)

    进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源. 系列文章 py ...

  5. Python核心技术与实战——十七|Python并发编程之Futures

    不论是哪一种语言,并发编程都是一项非常重要的技巧.比如我们上一章用的爬虫,就被广泛用在工业的各个领域.我们每天在各个网站.App上获取的新闻信息,很大一部分都是通过并发编程版本的爬虫获得的. 正确并合 ...

  6. Python核心技术与实战——十八|Python并发编程之Asyncio

    我们在上一章学习了Python并发编程的一种实现方法——多线程.今天,我们趁热打铁,看看Python并发编程的另一种实现方式——Asyncio.和前面协程的那章不太一样,这节课我们更加注重原理的理解. ...

  7. python并发编程之IO模型,

    了解新知识之前需要知道的一些知识 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调 ...

  8. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  9. python并发编程之IO模型(Day38)

    一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...

随机推荐

  1. Problem D - Non-boring sequences——Contest1004 - National Day Training Contest -- Day3

    今天比赛的时候做的一个坑题.深坑啊. 题目意思是给你一个有n个数的数字序列.要你判断对于这个序列是都满足任意一个子序列都至少含有一个只出现一次的数字. 看完题目后没什么思路,一直以为要用线段树,每次删 ...

  2. 【数据库_Mysql】Mysql知识汇总

    1.将多列字段合并显示用CONCAT(XX,XX,...): 2.查询表中某字段重复的数据: 查重复字段:select 字段 from table group by 字段 having count(* ...

  3. 【刷题】BZOJ 2753 [SCOI2012]滑雪与时间胶囊

    Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...

  4. C/C++语言中让电脑随机的在某个范围中的任一随机数

    这是我在笔试中碰见的一题中一部分,这就就记录下来.举例,输出[1,3]中任一随机数. #include<iostream> #include<cstdlib> #include ...

  5. Codeforces 906B. Seating of Students(构造+DFS)

    行和列>4的可以直接构造,只要交叉着放就好了,比如1 3 5 2 4和2 4 1 3 5,每一行和下一行用不同的方法就能保证没有邻居. 其他的可以用爆搜,每次暴力和后面的一个编号交换并判断可行性 ...

  6. 【bzoj4002】有意义的字符串

    Portal --> bzoj4002 Solution ​ 虽然说这题有点强行但是感觉还是挺妙的,给你通项让你反推数列的这种==有点毒 ​​ 补档时间 ​ 首先有一个东西叫做特征方程,我们可以 ...

  7. 【CF113D】Museum

    Portal --> cf113D Solution 额题意的话大概就是给一个无向图然后两个人给两个出发点,每个点每分钟有\(p[i]\)的概率停留,问这两个人在每个点相遇的概率是多少 如果说我 ...

  8. 关于使用EmguCV出现 “无法加载 DLL“cvextern”: 找不到指定的程序” 的解决方法

    http://blog.csdn.net/cdjcong/article/details/8444191 查找了网上的一些说法,都是说没有设置好路径,或者未将DLL文件复制到Debug文件夹下,但是我 ...

  9. Square Country

    原题链接:http://acm.timus.ru/problem.aspx?space=1&num=1073 分析:dp,dp[i]表示钱为i且恰好用完时能买的最少土地数,易知dp[i]=mi ...

  10. python并行编程学习之并行计算存储体系结构

    基于指令和可被同时处理的存储单元的数目,计算机系统可以分为以下四种类目: 单指令,单数据单元(SISD)在该体系结构中,计算机是单处理器机器,一次只能用单一的指令来操作单一的数据流.在SISD中,机器 ...