多进程

1. 进程创建的两种方式 multiprocessing

# 第一种方式
from multiprocessing import Process
import time def task(name):
print(f'{name} is running')
time.sleep(2)
print(f'{name} is gone') if __name__ == '__main__': # 在Windows环境下,必须在main下开启子进程
p = Process(target=task, args=('meet',)) # args元组形式 创建一个进程对象
p.start()
print("===主进程") """
结果:
===主进程
meet is running
meet is done
""" # p.start():开启子进程的命令,通知操作系统在内存中开辟一个进程空间,将主进程的数据copy加载到子进程空间中,然后操作系统调用cpu去执行子进程。 开销较大,因此会先执行主进程的代码。
# 第二种方式
from multiprocessing import Process
import time class MyProcess(Process): def __init__(self, name):
super().__init__() # 重构父类的方法
self.name = name
def run(self): # 必须写run()
print(f'{self.name} is running')
time.sleep(2)
print(f"{self.name} is gone") if __name__ == '__main__':
p = MyProcess('meet') # 默认执行run()
p.start() # 开启子进程的命令
print("===主进程")

2. 进程pid (process id)

进程在内存中的唯一标识。

终端命令: tasklist # 查看计算机当前所有进程的pid

终端命令: tasklist|findstr pycharm # 查看pycharm的pid

代码 :

import os
print(os.getpid()) # 查看当前进程的pid print(os.getppid()) # 查看父进程的pid

3. 验证进程之间的空间隔离

from multiprocessing import Process

lst = [1, 2]
def task():
lst.append(3)
print(f'子进程的:{lst}') if __name__ == '__main__':
p = Process(target=task)
p.start()
print(f'主进程的:{lst}')
"""
主进程的:[1, 2]
子进程的:[1, 2, 3]
"""
# 主进程与子进程之间存在空间隔离。

4. 进程对象join方法

join :让主进程等待子进程结束之后,再执行主进程。(让主进程阻塞)
from multiprocessing import Process
import time def task(sec):
print('is running')
time.sleep(sec)
print('is gone') if __name__ == '__main__':
start_time = time.time() p1 = Process(target=task, args=(1,))
p2 = Process(target=task, args=(2,))
p3 = Process(target=task, args=(3,))
p1.start()
p2.start()
p3.start()
# 同时开启
p1.join()
print(f'p1时间:{time.time()-start_time}') # 1s多
p2.join()
print(f'p2时间:{time.time()-start_time}') # 2s多
p3.join()
print(f'p3时间:{time.time()-start_time}') # 3s多
from multiprocessing import Process
import time def task(sec):
print('is running')
time.sleep(sec)
print('is gone') if __name__ == '__main__':
start_time = time.time() p1 = Process(target=task, args=(3,))
p2 = Process(target=task, args=(2,))
p3 = Process(target=task, args=(1,)) # 改变时间
p1.start()
p2.start()
p3.start()
# 同时开启
p1.join()
print(f'p1时间:{time.time()-start_time}') # 3s多 #阻塞
p2.join()
print(f'p2时间:{time.time()-start_time}') # 3s多
p3.join()
print(f'p3时间:{time.time()-start_time}') # 3s多
# 面试题:将下面代码优化
from multiprocessing import Process
import time def task(sec):
print('is running')
time.sleep(sec)
print('is gone') if __name__ == '__main__':
start_time = time.time() p1 = Process(target=task, args=(1,))
p2 = Process(target=task, args=(2,))
p3 = Process(target=task, args=(3,))
p1.start()
p2.start()
p3.start() p1.join()
p2.join()
p3.join()
print(f'运行时间:{time.time()-start_time}') # 3s多 # 上面代码优化:
lst = []
for i in range(1,4):
p = Process(target=task, args=(i,))
lst.append(p)
p.start() for i in lst:
i.join()
print(f'运行时间:{time.time()-start_time}') # 错误的优化:
for i in range(1,4)
p = Process(target=task, args=(i,))
p.start()
p.join()
print(f'运行时间:{time.time()-start_time}')

5. 进程对象其他属性

p.terminate()		# 结束子进程

p.is_alive()		# 判断子进程是否活着 True/False

p = Process(target=task, args=('meet',), age=18)	# 给子进程对象添加一个age属性。
print(p.age) # 18

6. 僵尸进程与孤儿进程

6.1 僵尸进程

实际中,主进程只有等待子进程结束后,主进程才结束。

基于Unix环境(linux,macOS):

主进程时刻监测子进程的运行状态,当子进程结束后,一段时间内,才会将子进程回收。

为什么不马上回收?

  1. 主进程与子进程是异步关系,主进程无法马上会获取子进程是什么时候结束;
  2. 如果子进程结束之后马上在内存中释放资源,主进程就没有办法监测子进程的状态。

Unix针对上面的问题,提供了一种机制:

所有的子进程结束后,立马释放掉文件的操作链接、内存等的大部分数据,但是会保留一些内容:进程号、结束时间、运行状态,等待子进程监测、回收。

僵尸进程:子进程在结束后,主进程并没有调用wait或waitpid获取子进程的状态信息,子进程仍然保留了一些描述内容,这种进程被称为僵尸进程。

​ 危害:如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样会占用内存,占用进程的pid号。

6.2 孤儿进程

父进程由于某种原因结束,但子进程还在运行中,则称这些子进程为孤儿进程。

回收机制:Unix中孤儿进程会被 init 进程回收,init 变成父进程。

僵尸进程解决方法

​ 直接杀死父进程。将所有僵尸进程变成孤儿进程,由 init进程回收。

7. 守护进程

# 子进程守护着主进程,只要主进程结束,子进程也跟着结束。

from multiprocessing import Process
import time def task(name):
print(f'{name} is running')
time.sleep(2)
print(f'{name} is gone') if __name__ == '__main__':
p = Process(target=task, args=('meet',)) # 创建一个进程对象
p.daemon = True # 放在start前,否则会报错。
p.start()
time.sleep(1)
print("===主进程")
"""
meet is running
===主进程
"""

python 33 多进程(一)的更多相关文章

  1. 『Python』多进程处理

    尝试学习python的多进程模组,对比多线程,大概的区别在: 1.多进程的处理速度更快 2.多进程的各个子进程之间交换数据很不方便 多进程调用方式 进程基本使用multicore() 进程池优化进程的 ...

  2. Python多线程多进程那些事儿看这篇就够了~~

    自己以前也写过多线程,发现都是零零碎碎,这篇写写详细点,填一下GIL和Python多线程多进程的坑~ 总结下GIL的坑和python多线程多进程分别应用场景(IO密集.计算密集)以及具体实现的代码模块 ...

  3. 【python】多进程锁multiprocess.Lock

    [python]多进程锁multiprocess.Lock 2013-09-13 13:48 11613人阅读 评论(2) 收藏 举报  分类: Python(38)  同步的方法基本与多线程相同. ...

  4. Python实现多进程

    Python可以实现多线程,但是因为Global Interpreter Lock (GIL),Python的多线程只能使用一个CPU内核,即一个时间只有一个线程在运行,多线程只是不同线程之间的切换, ...

  5. python 使用多进程实现并发编程/使用queue进行进程间数据交换

    import time import os import multiprocessing from multiprocessing import Queue, pool ""&qu ...

  6. Python多线程多进程

    一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...

  7. python中多进程+协程的使用以及为什么要用它

    前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重.切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL, ...

  8. Python的多进程

    这里不说其它,Python的多进程网上已经有很多了,可以尽情搜索.但是用多进程一般是采用对任务的方式,所以注意文件锁定.一般采用Pool是比较合适的.给个网友的小代码 from multiproces ...

  9. 进程,线程,以及Python的多进程实例

    什么是进程,什么是线程? 进程与线程是包含关系,进程包含了线程. 进程是系统资源分配的最小单元,线程是系统任务执行的最小单元. 打个比方,打开word,word这个程序是一个进程,里面的拼写检查,字数 ...

随机推荐

  1. [virtualenvwrapper] 命令小结

    创建环境 mkvirtualenv env1 mkvirtualenv env2 环境创建之后,会自动进入该目录,并激活该环境. 切换环境 workon env1 workon env2 列出已有环境 ...

  2. Python字符串格式化-学这些就够用了

    一.思考❓❔ 1.什么是字符串格式化? 将变量(对象)的值填充到字符串中 在字符串中解析Python表达式 对字符串进行格式化显示 左对齐.右对齐.居中对齐 保留数字有效位数 2.你学过的字符串格式化 ...

  3. C#中线程间操作无效: 从不是创建控件 txtBOX 的线程访问它。

    delegate void 委托名(方法名); void 方法名() { if(txtBox.invokeRequered) { 委托名 d=new 委托名(); txtBox.invoke(d); ...

  4. Java EE.JSP.概述

    JSP最终会被转换成标准Servlet,该转换过程一般出现在第一次请求页面时. JSP页面的主要组成部分如下: HTML 脚本:嵌入Java代码 指令:从整体上控制Servlet的结构 动作:引入现有 ...

  5. python课堂整理7---集合

    前面小节: sep 用来控制每个元素间的间隔符号 print("alex", "dabai", "liu", sep = "&qu ...

  6. JNDI资源(一)

    JNDI:Java命名与目录接口 是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录的通用.统一的服务. 使用JNDA的步骤: 1.配置资源. //Tomcat跟目录/conf/co ...

  7. 02-Kubenetes资源

    目录 Kubenetes资源 常用资源对象 标签labels 创建资源的方式 Pod pods.spec.containers 必须 nodeSelector <map [string]stri ...

  8. java抽奖思路

    现在在做一个有关抽奖的活动,将我自己所做的抽奖思路书写一下 1.项目奖项的配置存储在MongoDB 配置的参数为 奖项的等级(prizeLevel).数量(prizeNum).奖项的名称(prizeN ...

  9. Linux 常见的常识及常用快捷键方式

    1.  ,请写出linux系统中常见一级目录的名称及作用. /root :   超级用户的家目录 /home:  普通用户的家目录 /boot:   启动目录,启动相关文件(系统内核启动文件) /de ...

  10. win系统上Anaconda国内镜像配置

    清华镜像2019.6.15已恢复 中科大镜像2019.7.1停机维护后恢复 1.打开anaconda prompt 2.添加清华镜像1:https://mirrors.tuna.tsinghua.ed ...