zoukankan      html  css  js  c++  java
  • 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来彻底释放子进程的残留信息

  • 相关阅读:
    3.K均值算法
    2.机器学习相关数学基础
    1. 机器学习概述
    15、语法制导的语义翻译
    14、算符优先分析
    13、自下而上语法分析
    12、递归下降语法分析
    11、LL(1)文法的判断,递归下降分析程序
    10、消除左递归
    4.K均值算法--应用
  • 原文地址:https://www.cnblogs.com/lucky75/p/11122980.html
Copyright © 2011-2022 走看看