连衣裙一起做网站,网站开发计入无形资产吗,遵义网约车平台,windows10云电脑一 multiprocessing模块介绍 python中的多线程无法利用多核优势#xff0c;如果想要充分地使用多核CPU的资源#xff08;os.cpu_count()查看#xff09;#xff0c;在python中大部分情况需要使用多进程。Python提供了multiprocessing。 multiprocessing模块用来开启子进…一 multiprocessing模块介绍 python中的多线程无法利用多核优势如果想要充分地使用多核CPU的资源os.cpu_count()查看在python中大部分情况需要使用多进程。Python提供了multiprocessing。 multiprocessing模块用来开启子进程并在子进程中执行我们定制的任务比如函数该模块与多线程模块threading的编程接口类似。 multiprocessing模块的功能众多支持子进程、通信和共享数据、执行不同形式的同步提供了Process、Queue、Pipe、Lock等组件。 需要再次强调的一点是与线程不同进程没有任何共享状态进程修改的数据改动仅限于该进程内。 二 Process类的介绍 创建进程的类 Process([group [, target [, name [, args [, kwargs]]]]])由该类实例化得到的对象表示一个子进程中的任务尚未启动强调
1. 需要使用关键字的方式来指定参数
2. args指定的为传给target函数的位置参数是一个元组形式必须有逗号 参数介绍 1 group参数未使用值始终为None
2
3 target表示调用对象即子进程要执行的任务
4
5 args表示调用对象的位置参数元组args(1,2,egon,)
6
7 kwargs表示调用对象的字典,kwargs{name:egon,age:18}
8
9 name为子进程的名称 方法介绍 1 p.start()启动进程并调用该子进程中的p.run() 2 p.run():进程启动时运行的方法正是它去调用target指定的函数我们自定义类的类中一定要实现该方法 3 4 p.terminate():强制终止进程p不会进行任何清理操作如果p创建了子进程该子进程就成了僵尸进程使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放进而导致死锁5 p.is_alive():如果p仍然运行返回True6 7 p.join([timeout]):主线程等待p终止强调是主线程处于等的状态而p是处于运行的状态。timeout是可选的超时时间需要强调的是p.join只能join住start开启的进程而不能join住run开启的进程 属性介绍 1 p.daemon默认值为False如果设为True代表p为后台运行的守护进程当p的父进程终止时p也随之终止并且设定为True后p不能创建自己的新进程必须在p.start()之前设置
2
3 p.name:进程的名称
4
5 p.pid进程的pid
6
7 p.exitcode:进程在运行时为None、如果为–N表示被信号N结束(了解即可)
8
9 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性这类连接只有在具有相同的身份验证键时才能成功了解即可 三 Process类的使用 注意在windows中Process()必须放到# if __name__ __main__:下 Since Windows has no fork, the multiprocessing module starts a new Python process and imports the calling module. If Process() gets called upon import, then this sets off an infinite succession of new processes (or until your machine runs out of resources). This is the reason for hiding calls to Process() insideif __name__ __main__since statements inside this if-statement will not get called upon import.由于Windows没有fork多处理模块启动一个新的Python进程并导入调用模块。 如果在导入时调用Process那么这将启动无限继承的新进程或直到机器耗尽资源。 这是隐藏对Process内部调用的原使用if __name__ “__main __”这个if语句中的语句将不会在导入时被调用。详细解释 3.1创建开启子进程的两种方式 from multiprocessing import Processimport timedef task(name): print(%s is runing %(name)) time.sleep(3) print(%s is done % (name))if __name__ __main__: p Process(targettask,args(太白金星,)) # p Process(targettask,kwargs{name:太白金星}) 两种传参方式 p.start() print(主) from multiprocessing import Processimport time# 方式二:class MyProcess(Process): def __init__(self,name): self.name name super().__init__() def run(self): # 必须定义一个run方法 print(%s is runing % (self.name)) time.sleep(3) print(%s is done % (self.name)) if __name__ __main__: p MyProcess(太白金星) p.start() print(主) 3.2验证进程之间的空间隔离 # 接下来我们验证一下进程之间的互相隔离。# 在一个进程中x 1000## def task():# global x# x 2## task()# print(x)# 在不同的进程中# from multiprocessing import Process# import time# x 1000## def task():# global x# x 2## if __name__ __main__:# p Process(targettask)# p.start()# time.sleep(3)# print(x) 3.3 进程对象的join方法 from multiprocessing import Process
import time# 父进程等待子进程结束之后在执行
# 方法一 加sleep 不可取# def task(n):
# time.sleep(3)
# print(子进程结束....)
#
# if __name__ __main__:
# p Process(targettask,args(太白金星,))
# p.start()
# time.sleep(5)
# print(主进程开始运行....)
#
# 这样虽然达到了目的
# 1但是你在程序中故意加sleep极大影响程序的效率。
# 2sleep(3)只是虚拟子进程运行的时间子进程运行完毕的时间是不固定的。# 方法二 join# from multiprocessing import Process
# import time
#
#
# def task(n):
# time.sleep(3)
# print(子进程结束....)
#
#
# if __name__ __main__:
# p Process(targettask,args(太白金星,))
# p.start()
# p.join() # 等待p这个子进程运行结束之后在执行下面的代码主进程.
# print(主进程开始运行....)
#
# 接下来我要开启十个子进程先看看效果# from multiprocessing import Process
# import time
#
# def task(n):
# print(%s is running %n)
#
# if __name__ __main__:
# for i in range(1, 11):
# p Process(targettask,args(i,))
# p.start()
#
# 我这里是不是运行十个子进程之后才会运行主进程当然不会
# 1p.start()只是向操作系统发送一个请求而已剩下的操作系统在内存开启进程空间运行进程程序不一定是马上执行。
# 2开启进程的开销是比较大的。
#
# print(主进程开始运行....)# 那么有人说老师我对这个不理解我给你拆解开来。# from multiprocessing import Process
# import time
#
# def task(n):
# print(%s is running %n)
#
# if __name__ __main__:
# p1 Process(targettask,args(1,))
# p2 Process(targettask,args(2,))
# p3 Process(targettask,args(3,))
# p4 Process(targettask,args(4,))
# p5 Process(targettask,args(5,))
#
# p1.start()
# p2.start()
# p3.start()
# p4.start()
# p5.start()
#
# print(主进程开始运行....)# 接下来 实现起多子个进程然后等待这些子进程都结束之后在开启主进程。# from multiprocessing import Process
# import time
#
# def task(n):
# time.sleep(3)
# print(%s is running %n)
#
# if __name__ __main__:
# start_time time.time()
# p1 Process(targettask,args(1,))
# p2 Process(targettask,args(2,))
# p3 Process(targettask,args(3,))
# # 几乎同一个时刻发送三个请求
# p1.start()
# p2.start()
# p3.start()
# # 对着三个自己成使用三个join
#
# p1.join()
# p2.join()
# p3.join()
#
# print(time.time() - start_time,主进程开始运行....)
# # 3s 多一点点这是来回切换的所用时间。# 那么在进行举例# from multiprocessing import Process
# import time
#
# def task(n):
# time.sleep(n)
# print(%s is running %n)
#
# if __name__ __main__:
# start_time time.time()
# p1 Process(targettask,args(1,))
# p2 Process(targettask,args(2,))
# p3 Process(targettask,args(3,))
# # 几乎同一个时刻发送三个请求
# p1.start()
# p2.start()
# p3.start()
# # 对着三个自己成使用三个join
#
# p1.join() # 1s
# p2.join() # 2s
# p3.join() # 3s
#
# print(time.time() - start_time,主进程开始运行....)# 3s 多一点点这是来回切换的所用时间。# 利用for循环精简上面的示例# from multiprocessing import Process
# import time
#
# def task(n):
# time.sleep(1)
# print(%s is running %n)
#
# if __name__ __main__:
# start_time time.time()
# # for i in range(1,4):
# # p Process(targettask,args(i,))
# # p.start()
# # p.join()
#
# p1 Process(targettask,args(1,))
# p2 Process(targettask,args(2,))
# p3 Process(targettask,args(3,))
# # 几乎同一个时刻发送三个请求
# p1.start()
# p1.join()
# p2.start()
# p2.join()
# p3.start()
# p3.join()
# # 上面的代码p1.join()他的作用你的主进程代码必须等我的p1子进程执行完毕之后在执行
# # p2.start()这个命令是主进程的代码。
# # 而 如果你这样写
#
# p1.join()
# p2.join()
# p3.join()
#
#
# print(time.time() - start_time,主进程开始运行....)# 所以你上面的代码应该怎么写# from multiprocessing import Process
# import time
#
# def task(n):
# time.sleep(3)
# print(%s is running %n)
#
# if __name__ __main__:
# p_l []
# start_time time.time()
# for i in range(1,4):
# p Process(targettask,args(i,))
# p.start()
# p_l.append(p)
# # 对着三个自己成使用三个join
# for i in p_l:
# i.join()
# print(time.time() - start_time,主进程开始运行....) 3.4 进程对象的其他属性(了解) # from multiprocessing import Process# import time# import os## def task(n):# time.sleep(3)# print(%s is running %n,os.getpid(),os.getppid())## if __name__ __main__:# p1 Process(targettask,args(1,),name 任务1)# # print(p1.name) # 给子进程起名字# # for i in range(3):# # p Process(targettask, args(1,))# # print(p.name) # 给子进程起名字# p1.start()# # p1.terminate()# # time.sleep(2) # 睡一会他就将我的子进程杀死了。# # print(p1.is_alive()) # False# print(p1.pid)# # print(主)# print(os.getpid()) 3.5 僵尸进程与孤儿进程 一僵尸进程有害 僵尸进程一个进程使用fork创建子进程如果子进程退出而父进程并没有调用wait或waitpid获取子进程的状态信息那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。详解如下我们知道在unix/linux中正常情况下子进程是通过父进程创建的子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束如果子进程一结束就立刻回收其全部资源那么在父进程内将无法获取子进程的状态信息。因此UNⅨ提供了一种机制可以保证父进程可以在任意时刻获取子进程结束时的状态信息1、在每个进程退出的时候内核释放该进程所有的资源包括打开的文件占用的内存等。但是仍然为其保留一定的信息包括进程号the process ID退出状态the termination status of the process运行时间the amount of CPU time taken by the process等2、直到父进程通过wait / waitpid来取时才释放. 但这样就导致了问题如果进程不调用wait / waitpid的话那么保留的那段信息就不会释放其进程号就会一直被占用但是系统所能使用的进程号是有限的如果大量的产生僵死进程将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害应当避免。 任何一个子进程(init除外)在exit()之后并非马上就消失掉而是留下一个称为僵尸进程(Zombie)的数据结构等待父进程处理。这是每个子进程在结束时都要经过的阶段。如果子进程在exit()之后父进程没有来得及处理这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理可能用ps命令就来不及看到子进程的僵尸状态但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。二孤儿进程无害 孤儿进程一个父进程退出而它的一个或多个子进程还在运行那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养并由init进程对它们完成状态收集工作。 孤儿进程是没有父进程的进程孤儿进程这个重任就落到了init进程身上init进程就好像是一个民政局专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候内核就把孤 儿进程的父进程设置为init而init进程会循环地wait()它的已经退出的子进程。这样当一个孤儿进程凄凉地结束了其生命周期的时候init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。我们来测试一下创建完子进程后主进程所在的这个脚本就退出了当父进程先于子进程结束时子进程会被init收养成为孤儿进程而非僵尸进程文件内容import osimport sysimport timepid os.getpid()ppid os.getppid()print im father, pid, pid, ppid, ppidpid os.fork()#执行pidos.fork()则会生成一个子进程#返回值pid有两种值# 如果返回的pid值为0表示在子进程当中# 如果返回的pid值0表示在父进程当中if pid 0: print father died.. sys.exit(0)# 保证主线程退出完毕time.sleep(1)print im child, os.getpid(), os.getppid()执行文件输出结果im father pid 32515 ppid 32015father died..im child 32516 1看子进程已经被pid为1的init进程接收了所以僵尸进程在这种情况下是不存在的存在只有孤儿进程而已孤儿进程声明周期结束自然会被init来销毁。三僵尸进程危害场景 例如有个进程它定期的产 生一个子进程这个子进程需要做的事情很少做完它该做的事情之后就退出了因此这个子进程的生命周期很短但是父进程只管生成新的子进程至于子进程 退出之后的事情则一概不闻不问这样系统运行上一段时间之后系统中就会存在很多的僵死进程倘若用ps命令查看的话就会看到很多状态为Z的进程。 严格地来说僵死进程并不是问题的根源罪魁祸首是产生出大量僵死进程的那个父进程。因此当我们寻求如何消灭系统中大量的僵死进程时答案就是把产生大 量僵死进程的那个元凶枪毙掉也就是通过kill发送SIGTERM或者SIGKILL信号啦。枪毙了元凶进程之后它产生的僵死进程就变成了孤儿进 程这些孤儿进程会被init进程接管init进程会wait()这些孤儿进程释放它们占用的系统进程表中的资源这样这些已经僵死的孤儿进程 就能瞑目而去了。四测试#1、产生僵尸进程的程序test.py内容如下#coding:utf-8from multiprocessing import Processimport time,osdef run(): print(子,os.getpid())if __name__ __main__: pProcess(targetrun) p.start() print(主,os.getpid()) time.sleep(1000)#2、在unix或linux系统上执行[rootvm172-31-0-19 ~]# python3 test.py [1] 18652[rootvm172-31-0-19 ~]# 主 18652子 18653[rootvm172-31-0-19 ~]# ps aux |grep ZUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 18653 0.0 0.0 0 0 pts/0 Z 20:02 0:00 [python3] defunct #出现僵尸进程root 18656 0.0 0.0 112648 952 pts/0 S 20:02 0:00 grep --colorauto Z[rootvm172-31-0-19 ~]# top #执行top命令发现1zombietop - 20:03:42 up 31 min, 3 users, load average: 0.01, 0.06, 0.12Tasks: 93 total, 2 running, 90 sleeping, 0 stopped, 1 zombie%Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem : 1016884 total, 97184 free, 70848 used, 848852 buff/cacheKiB Swap: 0 total, 0 free, 0 used. 782540 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME COMMAND root 20 0 29788 1256 988 S 0.3 0.1 0:01.50 elfin #3、等待父进程正常结束后会调用waitwaitpid去回收僵尸进程但如果父进程是一个死循环永远不会结束那么该僵尸进程就会一直存在僵尸进程过多就是有害的解决方法一杀死父进程解决方法二对开启的子进程应该记得使用joinjoin会回收僵尸进程参考python2源码注释class Process(object): def join(self, timeoutNone): Wait until child process terminates assert self._parent_pid os.getpid(), can only join a child process assert self._popen is not None, can only join a started process res self._popen.wait(timeout) if res is not None: _current_process._children.discard(self)join方法中调用了wait告诉系统释放僵尸进程。discard为从自己的children中剔除 解决方法三http://blog.csdn.net/u010571844/article/details/50419798 四 守护进程 主进程创建守护进程 其一守护进程会在主进程代码执行结束后就终止 其二守护进程内无法再开启子进程,否则抛出异常AssertionError: daemonic processes are not allowed to have children 注意进程之间是互相独立的主进程代码运行结束守护进程随即终止 from multiprocessing import Processimport timeimport randomclass Piao(Process): def __init__(self,name): self.namename super().__init__() def run(self): print(%s is piaoing %self.name) time.sleep(random.randrange(1,3)) print(%s is piao end %self.name)pPiao(egon)p.daemonTrue #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行p.start()print(主) #主进程代码运行完毕,守护进程就会结束from multiprocessing import Processfrom threading import Threadimport timedef foo(): print(123) time.sleep(1) print(end123)def bar(): print(456) time.sleep(3) print(end456)p1Process(targetfoo)p2Process(targetbar)p1.daemonTruep1.start()p2.start()print(main-------) #打印该行则主进程代码结束,则守护进程p1应该被终止,可能会有p1任务执行的打印信息123,因为主进程打印main----时,p1也执行了,但是随即被终止 转载于:https://www.cnblogs.com/YZL2333/p/10445981.html