简介                               

  multiprocessing是一个使用类似于threading模块的API支持生成进程的包。该multiprocessing软件包提供本地和远程并发。因此,该multiprocessing模块允许程序员充分利用给定机器上的多个处理器。可以在Unix和Windows上运行。

multipleprocessing文档

Process(group=Nonetarget=Nonename=Noneargs=()kwargs={}*daemon=None)

应该始终使用关键字参数调用构造函数

  • group参数永远为None,该参数仅用于兼容threading.Thread
  • target应该是一个可以调用的对象,它会被run()方法调用
  • name是进程名
  • args是target所调用方法的参数
  • kwargs是target所调用方法的关键字参数
  • daemon默认为None,意味着从创建进程中继承,可设为True(守护进程)或False(非守护进程)

start()

  • 启动进程,只能调用一次,他会在进程中调用run方法

join([timeout])

  • 设主进程为m,子进程为s,m中调用s.join():阻塞m,直到s进程结束,timeout是一个正数,它最多会阻塞timeout秒 ,另外,s.join()可调用若干次
  • 一个进程p调用自己进程的join (p.join()) 可能会导致死锁【自己join自己这种骚操作不会,因此没实验】
  • 只能在调用s.start()后调用s.join()

  join可防止产生僵尸进程,文档中的编程指南中指出: 每次开启一个新进程,所有未被join的进程会被join(也就是说非守护进程会自动被join),但即便如此也要明确地join启动的所有进程。 因此如果不手动地join子线程,主进程也会等待子进程中止之后再中止

【另外join会影响守护进程的行为,后面探讨】

(一)Process开启进程:                       

# -*- coding:utf-8 -*-
import os
from multiprocessing import Process def func(name):
print('%s进程%d,父进程%d' % (name, os.getpid(), os.getppid())) '''
在Windows中,Process开启进程会再次导入此文件,为防止导入时再次执行,需要添加
if __name__ == '__main__':
'''
if __name__ == '__main__':
func('主')
p = Process(target=func, args=['子'])
p.start()
p.join()

 结果:

主进程16452,父进程21852
子进程28472,父进程16452

(二)自定义类继承Process,重写run方法               

  如果子类重写构造函数,则必须确保它在对进程执行任何其他操作之前调用构造函数 [Process.__init__() ]。

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os class InheritTest(Process): def __init__(self, name):
super().__init__()
self.name = name def run(self):
print('我是子进程%s,进程id=%d,父进程id=%d' % (self.name, os.getpid(), os.getppid()))
time.sleep(2) if __name__ == '__main__':
print('我是主进程, 进程id=%d,父进程id=%d' % (os.getpid(), os.getppid()))
p = InheritTest('小明')
p.start()
p.join()

结果:

我是主进程, 进程id=18408,父进程id=21852
我是子进程小明,进程id=22640,父进程id=18408

  若多个进程被join,阻塞时长是他们(包括主进程在这期间的执行时间)中执行时间最长的

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time def short_time():
print('进程pid={},ppid={}'.format(os.getpid(), os.getppid()))
time.sleep(2) def long_time():
print('进程pid={},ppid={}'.format(os.getpid(), os.getppid()))
time.sleep(4) if __name__ == "__main__":
p1 = Process(target=long_time)
p2 = Process(target=short_time)
p3 = Process(target=short_time)
p4 = Process(target=short_time) p1.start()
p2.start()
p3.start()
p4.start() print('1号进程阻塞中')
p1.join()
print('2号进程阻塞中')
p2.join()
print('3号进程阻塞中')
p3.join()
print('4号进程阻塞中')
p4.join() '''
p1-p4异步执行,p1执行时间最长,那么p1.join()阻塞完后,其它进程已经执行完了,
p2-p4.join()不阻塞,直接执行
'''

结果:

1号进程阻塞中
进程pid=26404,ppid=17928
进程pid=17960,ppid=17928
进程pid=15592,ppid=17928
进程pid=8724,ppid=17928
2号进程阻塞中
3号进程阻塞中
4号进程阻塞中

  问1:只能在父进程中join子进程吗?

  问1的解释: 在子进程中join其它同级的子进程会抛出异常 AssertionError: can only join a child process,因此只能在父进程中join子进程:

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os def func1():
time.sleep(2)
print('func1 进程pid={} ppid={}'.format(os.getpid(), os.getppid())) def func2(p1):
p1.join()
print('func2 进程pid={} ppid={}'.format(os.getpid(), os.getppid())) if __name__ == "__main__":
print('主进程id {}'.format(os.getpid()))
p1 = Process(target=func1)
p2 = Process(target=func2, args=[p1]) p2.start() # 和下面代码互换会报另一个异常
p1.start()
主进程id 14796
Process Process-2:
Traceback (most recent call last):
...............
AssertionError: can only join a child process
func1 进程pid=30100 ppid=14796

  

run()

  • 表示进程活动的方法。调用target指定的函数,如果有参数,会按顺序传入
  • 自定义进程类要在子类中覆盖此方法。

【单独调用run不会开启子进程】

is_alive()

  • 查看进程是否还活着。
  • 粗略地说,从start() 方法返回到子进程终止的那一刻,进程对象处于活动状态。

pid

  • 返回进程ID。在产生该过程之前,这将是 None

exitcode

  • 子进程的退出码,如果进程尚未中止,返回None,如果是-N,表示被信号N中止
# -*- coding:utf-8 -*-
import os
from multiprocessing import Process
import time def func(name):
print('%s进程%d,父进程%d' % (name, os.getpid(), os.getppid()))
if name != '主':
time.sleep(2) if __name__ == '__main__':
func('主')
p = Process(target=func, args=['子'])
p.start()
print('p.pid()', p.pid)
print('p.is_alive()=', p.is_alive())
print('p.exitcode=', p.exitcode)
p.join()
print('p.exitcode=', p.exitcode)
print('p.is_alive()=', p.is_alive())

结果

主进程1548,父进程21852
p.pid() 24000
p.is_alive()= True
p.exitcode= None
子进程24000,父进程1548
p.exitcode= 0
p.is_alive()= False

daemon

  • 进程的守护进程标志,一个布尔值。必须在start()调用之前设置 它。
  • 初始值继承自创建过程。
  • 当进程退出时(更确切地说是该进程的代码执行完毕后),它会尝试终止其所有守护子进程。
  • 不允许守护进程创建子进程。否则,守护进程会在进程退出时使这些进程变成孤儿进程。此外,这些不是Unix守护程序或服务,它们是正常进程,如果非守护进程已退出,它们将被终止(不会被join)。

(三)开启一个守护进程:                       

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os def daemon_func():
time.sleep(2)
print('守护进程pid={},ppid={}'.format(os.getpid(), os.getppid())) if __name__ == "__main__":
print('主进程id {}'.format(os.getpid()))
p = Process(target=daemon_func)
p.daemon = True
p.start()
# p.join()
当p.join()注释后,主进程中止,守护进程也中止,因此输出:
主进程id 15096
若取消注释,守护进程被join,主进程会等待此守护进程,输出为:
主进程id 10896
守护进程pid=19404,ppid=10896

(四) 主进程分别开启一个守护进程和非守护进程:            

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os # 守护进程p1执行
def daemon_func():
time.sleep(1)
print('daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) # 非守护进程p2执行
def non_daemon_func():
time.sleep(2)
print('non_daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) if __name__ == "__main__":
print('主进程id {}'.format(os.getpid())) p1 = Process(target=daemon_func)
p1.daemon = True
p2 = Process(target=non_daemon_func) p1.start()
p2.start()
  主进程执行完立即中止守护进程(主进程此时自己没中止),主进程等待非守护进程,然后中止
因此执行结果是:
主进程id 24588
non_daemon_func 进程pid=3772,ppid=24588 ### 这里ppid是24588,而不是1,说明主进程还未中止

(4.1)守护进程被join:

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os # 守护进程p1执行
def daemon_func():
time.sleep(1)
print('daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) # 非守护进程p2执行
def non_daemon_func():
time.sleep(2)
print('non_daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) if __name__ == "__main__":
print('主进程id {}'.format(os.getpid())) p1 = Process(target=daemon_func)
p1.daemon = True
p2 = Process(target=non_daemon_func) p1.start()
p2.start() p1.join() # join守护进程
主进程执行完后没中止守护进程,并等待非守护进程执行完:
主进程id 24416
daemon_func 进程pid=27312,ppid=24416
non_daemon_func 进程pid=12408,ppid=24416
守护进程睡三秒,主进程仍会等待守护进程执行完:
主进程id 20336
non_daemon_func 进程pid=24528,ppid=20336
daemon_func 进程pid=16596,ppid=20336

  守护进程被join后,主进程会等待守护进程执行完。因此,join守护进程,还不如直接开非守护进程

(4.2)非守护进程被join

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time
import os # 守护进程p1执行
def daemon_func():
time.sleep(1)
print('daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) # 非守护进程p2执行
def non_daemon_func():
time.sleep(2)
print('non_daemon_func 进程pid={},ppid={}'.format(os.getpid(), os.getppid())) if __name__ == "__main__":
print('主进程id {}'.format(os.getpid())) p1 = Process(target=daemon_func)
p1.daemon = True
p2 = Process(target=non_daemon_func) p1.start()
p2.start() p2.join() # join非守护进程
非守护进程被join,主进程等待非守护进程,非守护进程中止后,立即中止守护进程。
------------------------------------------------------------------------------
注意【1.主进程只join非守护进程】和【2.主进程没有join任何进程】的区别:
1: 主进程会被join阻塞,等到非守护进程中止后,中止守护进程 2: 主进程执行完立即中止守护进程,若非守护进程未中止,等待 其实都是主进程的代码执行完毕后,才中止子守护进程,只是1包含了手动join进程的代码,阻塞后代码才算执行完毕。
-----------------------------------------------------------------
守护进程睡1秒后,非守护进程还在睡,主进程被阻塞住,因此守护进程有输出
主进程id 11284
daemon_func 进程pid=5308,ppid=11284
non_daemon_func 进程pid=30364,ppid=11284
守护进程睡3秒后,非守护进程在2秒时睡醒后中止,主进程便在此时中止守护进程,因此守护进程没有输出
主进程id 24912
non_daemon_func 进程pid=19892,ppid=24912

join在很多地方都有用到,预知join的行为并合理利用join,避免产生死锁

terminate()

  中止进程,在Unix上是用SIGTERM信号完成的;在Windows上,使用TerminateProcess();

  注意,退出处理程序和finally子句等不会被执行

  被中止进程的子进程不会被中止

  避免使用此方法:使用该方法停止进程可能导致进程当前使用的任何共享资源被破坏或不可用于其它进程,最好只考虑该方法用在从不使用共享资源的进程上

参考:

官方文档

如有意见或建议,一起交流;如有侵权,请告知删除。

python多进程——multiprocessing.Process的更多相关文章

  1. 转 Python 多进程multiprocessing.Process之satrt()和join()

    1. https://blog.csdn.net/wonengguwozai/article/details/80325745 今天项目中涉及到了使用多进程处理数据,在廖雪峰的python教程上学习了 ...

  2. Python 多进程 multiprocessing.Pool类详解

    Python 多进程 multiprocessing.Pool类详解 https://blog.csdn.net/SeeTheWorld518/article/details/49639651

  3. Python多进程multiprocessing使用示例

    mutilprocess简介 像线程一样管理进程,这个是mutilprocess的核心,他与threading很是相像,对多核CPU的利用率会比threading好的多. import multipr ...

  4. Python 多进程multiprocessing

    一.python多线程其实在底层来说只是单线程,因此python多线程也称为假线程,之所以用多线程的意义是因为线程不停的切换这样比串行还是要快很多.python多线程中只要涉及到io或者sleep就会 ...

  5. python ---多进程 Multiprocessing

    和 threading 的比较 多进程 Multiprocessing 和多线程 threading 类似, 他们都是在 python 中用来并行运算的. 不过既然有了 threading, 为什么 ...

  6. python多进程-----multiprocessing包

    multiprocessing并非是python的一个模块,而是python中多进程管理的一个包,在学习的时候可以与threading这个模块作类比,正如我们在上一篇转载的文章中所提,python的多 ...

  7. python多进程multiprocessing Pool相关问题

    python多进程想必大部分人都用到过,可以充分利用多核CPU让代码效率更高效. 我们看看multiprocessing.pool.Pool.map的官方用法 map(func, iterable[, ...

  8. 操作系统OS,Python - 多进程(multiprocessing)、多线程(multithreading)

    多进程(multiprocessing) 参考: https://docs.python.org/3.6/library/multiprocessing.html 1. 多进程概念 multiproc ...

  9. python多进程(multiprocessing)

    最近有个小课题,需要用到双进程,翻了些资料,还算圆满完成任务.记录一下~ 1.简单地双进程启动 同时的调用print1()和print2()两个打印函数,代码如下: #/usr/bin/python ...

随机推荐

  1. BZOJ2140 稳定婚姻[强连通分量]

    发现如果$B_i$和$G_j$配对,那么$B_j$又要找一个$G_k$配对,$B_k$又要找一个$G_l$配对,一直到某一个$B_x$和$G_i$配对上为止,才是不稳定的. 暴力是二分图匹配.匈牙利算 ...

  2. 如何定义搜索面板的过滤器?DevExpress WPF超easy

    DevExpress广泛应用于ECM企业内容管理. 成本管控.进程监督.生产调度,在企业/政务信息化管理中占据一席重要之地.通过DevExpress WPF Controls,您能创建有着强大互动功能 ...

  3. git 解决 error: failed to push some refs to 'https://github.com/xxxx.git'

    在github远程创建仓库后, 利用gitbash进行提交本地文件的时候出现如下错误 [root@foundation38 demo]# git push -u origin master Usern ...

  4. Jquery开发&BootStrap 实现“todolist项目”

    作业题目:实现“todolist项目” 作业需求: 基础需求:85%参考链接http://www.todolist.cn/1. 将用户输入添加至待办项2. 可以对todolist进行分类(待办项和已完 ...

  5. 斑马105SLPlus串口打印二维码

    1.根据说明书调试硬件,校准介质还有色带(很重要),我自己搞了好几天才搞明白. 2.设置好参数,比如打印介质连续.非连续,热敏还是热转质 3.打印机上电后悔自动校准,校准成功后就可以直接通过串口打印, ...

  6. [Luogu] 天天爱跑步

    https://www.luogu.org/problemnew/show/P1600 https://www.zybuluo.com/wsndy-xx/note/1135243 乱写的暴力,这道题暴 ...

  7. [NOI2017]蚯蚓排队

    嘟嘟嘟 现在看来这道题还不是特别难. 别一看到字符串就想SAM 看到\(k\)很小,所以我们可以搞一个单次修改复杂度跟\(k\)有关的算法. 能想到,每一次断开或链接,最多只会影响\(k ^ 2\)个 ...

  8. 【线性代数】2-6:三角矩阵( $A=LU$ and $A=LDU$ )

    title: [线性代数]2-6:三角矩阵( A=LUA=LUA=LU and A=LDUA=LDUA=LDU ) toc: true categories: Mathematic Linear Al ...

  9. P2699 【数学1】小浩的幂次运算

    原题链接 https://www.luogu.org/problemnew/show/P2699 P2699 [数学1]小浩的幂次运算 首先第一眼看这个题就知道要暴力枚举w^i 看是否在区间[l,r] ...

  10. Could not initialize class sun.awt.X11GraphicsEnvironment异常处理

    原因导致: 经过Google发现很多人也出现同样的问题.从了解了X11GraphicEnvironment这个类的功能入手, 一个Java服务器来处理图片的API基本上是需要运行一个X-server以 ...