Python如何使用多进程

Python如何使用多进程

  • 创建子进程的方式

1.导入multiprocessing中的Process类,并且实例化这个类,指定要执行的任务(如函数)target

import os
from multiprocessing import Process

# Process就表示进程,在很多地方都是这样

def task():
    print('this is sub process')
    print(f'sub process id {os.getpid()}')
    
# 注意,开启进程的代码必须放在__main__判断下面,不然会循环导入,下面会详细解释
if __name__ == '__main__':
    # 实例化一个进程对象
    p = Process(target=task)
    p.start() # 给操作系统发送指令,让它开启进程
    # 如果子进程只使用一次且没什么操作,可以直接这样用
    # Process(target=task).start()
    print('this is parent process')
    print(f'parent process is {os.getpid()}')
this is parent process
parent process is 2060
this is sub process
sub process id 10008

为什么要写在main下面

linux 与 windows 开启进程的方式不同

linux 会将父进程的内存数据完整copy一份给子进程

windows 会导入父进程的代码,并且从头执行一遍,来获取需要处理的任务

所以在编写代码时一定要将开启进程的代码放在main判断中,否则就会循环导入

2.导入multiprocessing 中的Process类,继承这个类,覆盖run方法,将要执行的任务放入run中,开启进程时则会自动执行该函数

  • 在需要对进程对象进行高度自定义时使用
from multiprocessing import Process
import os

class Downloader(Process):
    
    # def __init__(self, url, size, name):
    #	super().__init__()
    #	self.url = url
    # 	self.size = size
    #	self.name = name
    
   	def run(self):
        print(os.getpid())
        
if __name__ == '__main__':
    m = Downloader()
	m.start()	# 这里不要使用run(),因为那样只是运行方法而不是开启进程
    print('parent over', os.getpid())
parent over 1756	# 父进程打印的
parent over 4048	# 子进程打印的
4048				# 子进程的run()中打印的

从这个例子的打印顺序中可以得知:开启子进程需要时间,所以会先执行父进程

进程之间相互隔离

1.可以在开启进程后使用sleep方法,但是这样做并不好,因为你无法确定这个子进程到底会运行多久

join函数

  • 主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
from multiprocessing import Process

def task1(name):
    for i in range(100):
        print(f'{name} run')
        
def task2(name):
    for i in range(100):
        print(f'{name} run')
        
if __name__ == '__main__':	   # args 是给子进程传参的,必须是元祖
    p1 = Process(target=task1, args=('p1',))
    p1.start()
    
    p2 = Process(target=task2, args=('p2',))
    p2.start()
    
    p2.join()	# 让主进程,等待子进程执行完毕后再继续执行
    p1.join()
    
    # 达到的效果是,保证两个子进程是并发执行的,并且over一定是在最后打印
  	print('over')

案例:

from multiprocessing import Process

def task1(name):
    for i in range(10):
        print(f'{name} run')
        
if __name__ == '__main__':
    ps=[]	# 需要把每一个进程添加到列表中
    for i in range(10):
        p = Process(target=task1, args=(i,))
        p.start()
        ps.append(p)
        
    for i in ps:	# 遍历列表,保证每一个子进程都已经结束了
        i.join()
        
    # 达到的效果是,把100个打印,分给10个子进程去做,最后打印over   
    print('over')

进程对象的常用属性(了解)

方法名 作用
p.name 打印进程名,可以在实例化时添加name参数
p.daemon 守护进程
p.exitcode 获取进程的退出码(就是exit()函数中传入的值)
p.is_alive() 查看进程是否存活
p.pid() 获取进程id(子进程)
p.terminate() 终止进程,与start相同,不会立即终极,操作系统需要时间

僵尸进程与孤儿进程(了解)

孤儿进程 当父进程已经结束,而子进程还在运行,子进程就称为孤儿进程,比如用QQ打开了浏览器,再退掉QQ,那么浏览器就是孤儿进程,这个有其存在的必要性,没有不良影响,孤儿进程会被操作系统所接管

僵尸进程 当一个进程已经结束了,但是它仍然还有一些数据存在,此时称之为僵尸进程

在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的一些数据

子进程任务执行完毕后,确实结束了但是仍然保留一些数据,目的是为了让父进程能够获取信息

linux中,可以调用waitpid来彻底释放子进程的残留信息

posted @ 2019-07-02 20:31  abcde_12345  阅读(605)  评论(0编辑  收藏  举报