python多进程——multiprocessing.Process
简介
multiprocessing
是一个使用类似于threading
模块的API支持生成进程的包。该multiprocessing
软件包提供本地和远程并发。因此,该multiprocessing
模块允许程序员充分利用给定机器上的多个处理器。可以在Unix和Windows上运行。
Process
(group=None, target=None, name=None, args=(), 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的更多相关文章
- 转 Python 多进程multiprocessing.Process之satrt()和join()
1. https://blog.csdn.net/wonengguwozai/article/details/80325745 今天项目中涉及到了使用多进程处理数据,在廖雪峰的python教程上学习了 ...
- Python 多进程 multiprocessing.Pool类详解
Python 多进程 multiprocessing.Pool类详解 https://blog.csdn.net/SeeTheWorld518/article/details/49639651
- Python多进程multiprocessing使用示例
mutilprocess简介 像线程一样管理进程,这个是mutilprocess的核心,他与threading很是相像,对多核CPU的利用率会比threading好的多. import multipr ...
- Python 多进程multiprocessing
一.python多线程其实在底层来说只是单线程,因此python多线程也称为假线程,之所以用多线程的意义是因为线程不停的切换这样比串行还是要快很多.python多线程中只要涉及到io或者sleep就会 ...
- python ---多进程 Multiprocessing
和 threading 的比较 多进程 Multiprocessing 和多线程 threading 类似, 他们都是在 python 中用来并行运算的. 不过既然有了 threading, 为什么 ...
- python多进程-----multiprocessing包
multiprocessing并非是python的一个模块,而是python中多进程管理的一个包,在学习的时候可以与threading这个模块作类比,正如我们在上一篇转载的文章中所提,python的多 ...
- python多进程multiprocessing Pool相关问题
python多进程想必大部分人都用到过,可以充分利用多核CPU让代码效率更高效. 我们看看multiprocessing.pool.Pool.map的官方用法 map(func, iterable[, ...
- 操作系统OS,Python - 多进程(multiprocessing)、多线程(multithreading)
多进程(multiprocessing) 参考: https://docs.python.org/3.6/library/multiprocessing.html 1. 多进程概念 multiproc ...
- python多进程(multiprocessing)
最近有个小课题,需要用到双进程,翻了些资料,还算圆满完成任务.记录一下~ 1.简单地双进程启动 同时的调用print1()和print2()两个打印函数,代码如下: #/usr/bin/python ...
随机推荐
- wordpress网站不正常显示解决办法
第一种:自己在后台修改了wordpress网址,导致不能登陆后台. 解决办法: 1.首先我们登录MySql数据库,这个不用我教吧: 2.查看表”wp_options”的数据(你的表不一定是以”wp”开 ...
- pandas.DataFrame.where和mask 解读
1.前言背景 没怎么用过df.where 都是直接使用loc.apply等方法去解决. 可能是某些功能还没有超出loc和apply的适用范围. 2.进入df.where和df.mask DataFra ...
- bzoj1458: 士兵占领(最大流)
题目描述 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵 ...
- Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH)
Filtering Approaches for Real-Time Anti-Aliasing(2011 SIGGRAPH) 在2011的SIGGRAPH上,NVIDA提出了FXAA3.1,本文主要 ...
- C# 操作服务命令
安装服务 @echo.服务启动...... @echo off @sc create 服务名称 binPath= " exe地址" @net start 服务名称 @sc conf ...
- Spring Boot 前期篇
在学习springboot之前,学习一下Spring的java配置. 1. Spring的发展 1.1. Spring1.x 时代 在Spring1.x时代,都是通过xml文件配置bean,随着项目的 ...
- luogu 4411 [BJWC2010]取数游戏 约数+dp
不大难的dp,暴力拆一下约数然后按照约数来统计即可. 注意:vector 很慢,所以一定特判一下,如果没有该数,就不要添加. Code: #include <bits/stdc++.h> ...
- SVN - Subversion
Subversion yum install -y subversion 或者 subversion Edge 下载: # wget https://downloads-guests.open.col ...
- JavaWeb_(SSH)三大框架整合struts+hibernate+spring_Demo
三大框架整合 一.SSH导包 二.书写Spring 三.书写Struts 四.整合Spring与Struts 五.书写(与整合)Hibernate.引入c3p0连接池并使用hibernate模板 六. ...
- MySql数据类型及对应存储空间
整数型数据类型 类型名称 说明 存储需求 TINYINT 很小的正数 1个字节 SMALLINT 小正数 2个字节 MEDIUMINT 中等大小的正数 3个字节 INT(INTEGER) 普通大小的正 ...