GVKun编程网logo

multiprocessing.Process(使用spawn方法):继承了哪些对象?(multiprocessing spawn)

19

如果您想了解multiprocessing.Process的相关知识,那么本文是一篇不可错过的文章,我们将对使用spawn方法:继承了哪些对象?进行全面详尽的解释,并且为您提供关于(并发编程)进程(m

如果您想了解multiprocessing.Process的相关知识,那么本文是一篇不可错过的文章,我们将对使用spawn方法:继承了哪些对象?进行全面详尽的解释,并且为您提供关于(并发编程)进程 (multiprocessing--Process实现进程并发)、day 32 multiprocessing 模块中 Process 方法,僵尸进程,孤儿进程,守护进程、multiprocessing.process的用法、parallel.futures中的ProcessPoolExecutor比multiprocessing.Pool慢的有价值的信息。

本文目录一览:

multiprocessing.Process(使用spawn方法):继承了哪些对象?(multiprocessing spawn)

multiprocessing.Process(使用spawn方法):继承了哪些对象?(multiprocessing spawn)

docs(python 3.4)通过进行了解释spawn,“子进程将仅继承运行进程对象的run()方法所需的那些资源”。

但是哪些对象是“必需的”?我阅读它的方式告诉我,从内部可以到达的所有对象run()都是“必需的”,包括传递args给的参数Process.__init__,以及存储在全局变量中的所有内容,以及在全局范围内定义的类,函数及其属性。但是,这是不正确的。以下代码确认未继承全局变量中存储的对象:

# running under python 3.4 / Windows# but behaves the same under Uniximport multiprocessing as mpx = 0class A:    y = 0def f():    print(x) # 0    print(A.y) # 0def g(x, A):    print(x) # 1    print(A.y) # 0; really, not even args are inherited?def main():    global x    x = 1    A.y = 1    p = mp.Process(target = f)    p.start()    q = mp.Process(target = g, args = (x, A))    q.start()if __name__=="__main__":    mp.set_start_method(''spawn'')    main()

是否有明确的规则规定要继承哪些对象?

编辑:

确认:在Ubuntu上运行会产生相同的输出。(感谢@mata阐明我忘了添加globalxmain()。)这一遗漏使我的示例感到困惑;如果我切换''spawn''''fork''Ubuntu下,也会影响结果。我现在添加globalx到上面的代码中。)

答案1

小编典典

这与将类发送到派生的Process时对其进行腌制的方式有关。类的腌制版本实际上并不包含其内部状态,而仅包含模块和类的名称:

class A:   y = 0pickle.dumps(A)# b''\x80\x03c__main__\nA\nq\x00.''

这里没有任何信息y,可以与对该类的引用进行比较。

当以argumeht的形式传递给时g,该类将在生成的进程中被取消选择,该类将在必要时导入其模块(在__main__)并返回对该类的引用,因此在main函数中对其进行的更改不会影响该类,因为会if__name__ == "__main__"赢得该块不会在子流程中执行。f直接在其模块中使用该类,因此效果基本相同。

x显示不同值的原因略有不同。您的f函数将从模块中打印 全局 变量x。在您的main()函数中,您还有另一个 局部
变量x,因此在两个进程中,x = 1此处的设置都不会影响模块级别x。它g作为参数传递给它,因此在这种情况下,它将保留本地值为1。

(并发编程)进程 (multiprocessing--Process实现进程并发)

(并发编程)进程 (multiprocessing--Process实现进程并发)

[''创建进程2方式种'',
''进程对象属性:join方法,守护进程obj.daemon=True,obj.pid, obj.name, obj.terminate(),obj.is_alive()等 ''
''os.getpid,os.getppid'',
''互斥锁(Lock())'',
''僵尸进程与孤儿进程'',
''内存空间物理上隔离'']
并发的本质:切换+保持状态

一、同一个程序执行多次是多个进程
每一个进程有一个PID
import os
os.getppid()   #父的pid (pycharm.exe)#cmd 中 pyhon 路径 父的pid(cmd.exe)
os.getpid()    #自己的pid (python.exe)
二、开启子进程的两种方式
windows (createprocess) 创建子进程时子辈除了拷贝父辈的信息还创建了些自己的东西
unix (fork) 创建子进程时拷贝父辈的信息子进程的初始状态和父辈一致
第一种(比较常用)                                                                                                                                                                                                           
from multiprocessing import Process                                                                                                                                                                                 
import time                                                                                                                                                                                                         
                                                                                                                                                                                                                    
def task(name):                                                                                                                                                                                                     
    print(''%s is running'' %name)                                                                                                                                                                                    
    time.sleep(3)                                                                                                                                                                                                   
    print(''%s is done'' %name)                                                                                                                                                                                       
                                                                                                                                                                                                                    
if __name__ == ''__main__'':                                                                                                                                                                                          
    # 在windows系统之上,开启子进程的操作一定要放到这下面                                                                                                                                                                                 
    # Process(target=task,kwargs={''name'':''egon''})   #两种传参方式皆可                                                                                                                                                        
    p=Process(target=task,args=(''egon'',))          #两种传参方式皆可                                                                                                                                                        
    p.start() # 向操作系统发送请求,操作系统会申请内存空间,把父进程的数据拷贝给子进程,作为子进程的初始状                                                                                                                          
    print(''======主'')                                                                                                                                                                                                
                                                                                                                                                                                                                    
第二种                                                                                                                                                                                                                 
from multiprocessing import Process                                                                                                                                                                                 
import time                                                                                                                                                                                                         
                                                                                                                                                                                                                    
class MyProcess(Process):                                                                                                                                                                                           
    def __init__(self,name):                                                                                                                                                                                        
        super(MyProcess,self).__init__()     #Process在init里面有相应设置,要遗传下来,否则报错                                                                                                                                        
        self.name=name                                                                                                                                                                                              
                                                                                                                                                                                                                    
    def run(self):                                                                                                                                                                                                  
        print(''%s is running'' %self.name)                                                                                                                                                                           
        time.sleep(3)                                                                                                                                                                                               
        print(''%s is done'' %self.name)                                                                                                                                                                              
                                                                                                                                                                                                                    
if __name__ == ''__main__'':                                                                                                                                                                                          
    p=MyProcess(''egon'')                                                                                                                                                                                             
    p.start()   #p.start()调用了类中的run()方法(规定)                                                                                                                                                                         
print(''主'')
三、进程的内存空间相互隔离
from multiprocessing import Process                    
import time                                            
                                                       
x=1000                                                                                                       
def task():                                            
    time.sleep(3)                                      
    global x                                           
    x=0                                                
    print(''儿子死啦'',x)                                    
#在之前最好只有函数或变量的定义,没有具体的执行(print等)                                                       
if __name__ == ''__main__'':                                                                      
    p=Process(target=task)                             
    p.start()                                          
    time.sleep(5)                                      
print(x)    
#在子进程中对变量x的修改不影响父进程中x的值
四、父进程等待子进程结束 p1.join()
#(等待p1 卡住)等儿子死了,wait回收儿子的pid等遗留下的东西
#了解 连续start再连续join 和 连续start,join。。。。
from multiprocessing import Process                                    
import time                                                            
                                                                       
x=1000                                                                                        
def task(n):                                                           
    print(''%s is runing'' %n)                                           
    time.sleep(n)                                                      
                                                                       
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()                                                         
                                                                       
    p3.join() #3s                                                      
    p1.join()                                                          
    p2.join()                                                      
                                                                       
print(''主'',(time.time() - start_time))        #3.01637601852417     
#用循环
from multiprocessing import Process                                  
import time                                                          
                                                                     
x=1000                                                               
                                                                     
def task(n):                                                         
    print(''%s is runing'' %n)                                         
    time.sleep(n)                                                    
                                                                     
if __name__ == ''__main__'':                                           
    start_time=time.time()                                           
    p_l=[]                                                           
    for i in range(1,4):                                             
        p=Process(target=task,args=(i,))                             
        p_l.append(p)                                                
        p.start()                                                    
                                                                     
    for p in p_l:                                                    
        p.join()                                                     
                                                                     
print(''主'',(time.time() - start_time))       #3.0141923427581787
五、进程对象的其他属性
from multiprocessing import Process                                     
import time                                                             
                                                                        
def task(n):                                                            
    print(''%s is runing'' %n)                                            
    time.sleep(n)                                                       
                                                                        
if __name__ == ''__main__'':   # 在windows系统之上,开启子进程的操作一定要放到这下面                                            
    start_time=time.time()                                              
    p1=Process(target=task,args=(1,),name=''任务1'') 
    p1 daemon=True    #再obj发出创建前,将obj变成守护进程,主进程执行完毕后子进程跟着结束
    p1.start()         #向操作系统发创建子进程请求,父进程无需等待                                                    
    print(p1.pid)                                                       
    print(p1.name)     #如前面不定义name,默认process-1 etc                      
    p1.terminate()     #向操作系统发请求,父进程无需等待                            
    p1.join()          #等待该子进程结束(卡住吧),父进程需要等待一点时间                                                
    print(p1.is_alive())                                                
    print(''主'')       #这里的效果是主进程等儿子死了,再结束
from multiprocessing import Process                         
import time,os                                              
                                                            
def task():                                                 
    print(''self:%s parent:%s'' %(os.getpid(),os.getppid()))  
    time.sleep(3)                                           
                                                            
if __name__ == ''__main__'':                                  
    p1=Process(target=task,)                                
    p1.start()                                              
    print(p1.pid)                                           
print(''主'',os.getpid())  
六、僵尸进程与孤儿进程
在unix系统中init是所有进程的爹;创建进程用fork,回收进程(结束进程的残留信息?)用waitpid
僵尸进程(有害:占用pid):子代先于父代终结,其部分信息(pid等)没有从系统中删除,需要父代回收。join中含有回收子代信息的功能。
孤儿进程(无害):父代先于子代终结,子代终结后的部分信息由init代收。
from multiprocessing import Process                     
import time,os                                          
                                                        
def task(n):                                            
    print(''%s is running'' %n)                           
    time.sleep(n)                                       
                                                        
if __name__ == ''__main__'':       
 1=Process(target=task,args=(1,))                   
    p1.start()                                          
    p1.join()     # join中含有回收子代信息的功能(wait)                                      
    print(''======主'',os.getpid()) 
 
 
七、守护进程
父进程  代码运行完(主线程运行代码),守护进程就结束
from multiprocessing import Process
import time
def task(name):
    print(''%s is running'' % name)
    time.sleep(3)
if __name__ == ''__main__'':
    obj = Process(target=task, args=(''egon'',))
    obj.daemon=True    #将obj变成守护进程,主进程执行完毕后子进程跟着结束
    obj.start()  # 发送信号给操作系统
  print(''主'')
八、互斥锁
强调:必须是lock.acquire()一次,然后 lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire()。否者程序停在原地。
     抢同一把锁:生成锁对象 必须放在if __name__==''__main__'': 下面
互斥锁vs join
大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序(在多个程序共享一个资源时,为保证有序不乱,需将并发变成串行)
场景: 修改公共数据,如果并发会发出数据错乱,这时就必须串行执行,就要用到互斥锁
区别一:join是按照人为指定的顺序执行,而互斥锁是所以进程平等地竞争,谁先抢到谁执行
区别二:互斥锁可以让一部分代码串行,而join只能将代码整体串行(详见抢票系统)
  理解:首先join肯定是一个子进程对象,互斥锁可以加在子进程对象代码任意部位(要释放额)
     join人为安排子进程执行顺序,互斥锁是公平竞争。
  
from multiprocessing import Process,Lock
import time,random
mutex=Lock()  #这里每个子进程的都会申请一把锁
print(id(mutex))
def task1(lock):
     lock.acquire()
 #   print(''task1:名字是egon'')
 #   time.sleep(random.randint(1,3))
 #   print(''task1:性别是male'')
     time.sleep(random.randint(1,3))      #with mutex: time.sleep(random.randint(1,3))
 #   print(''task1:年龄是18'')        
     lock.release()
def task2(lock):
    lock.acquire()
    print(''task2:名字是alex'')
    time.sleep(random.randint(1,3))
    print(''task2:性别是male'')
    time.sleep(random.randint(1,3))
    print(''task2:年龄是78'')
    lock.release()
def task3(lock):
    lock.acquire()
    print(''task3:名字是lxx'')
    time.sleep(random.randint(1,3))
    print(''task3:性别是female'')
    time.sleep(random.randint(1,3))
    print(''task3:年龄是30'')
    lock.release()
if __name__ == ''__main__'':
    p1=Process(target=task1,args=(mutex,))
    p2=Process(target=task2,args=(mutex,))
    p3=Process(target=task3,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
last、抢票系统
import json
import time
import random
import os
from multiprocessing import Process,Lock
mutex=Lock()  #每个子进程都会生成  一把锁对象,没用到。可以优化放在下面 __name__里面
def search():
    time.sleep(random.randint(1,3))
    with open(''db.json'',''r'',encoding=''utf-8'') as f:
        dic=json.load(f)
        print(''%s 剩余票数:%s'' %(os.getpid(),dic[''count'']))
def get():
    with open(''db.json'',''r'',encoding=''utf-8'') as f:
        dic=json.load(f)
    if dic[''count''] > 0:
        dic[''count'']-=1
        time.sleep(random.randint(1,3))
        with open(''db.json'',''w'',encoding=''utf-8'') as f:
            json.dump(dic,f)
        print(''%s 购票成功'' %os.getpid())
def task(lock):
    search()
    lock.acquire()
    get()
    lock.release()
if __name__ == ''__main__'':
    for i in range(10):
        p=Process(target=task,args=(mutex,)) #这里子进程用的都是主进程这一把锁 id
        p.start()

day 32 multiprocessing 模块中 Process 方法,僵尸进程,孤儿进程,守护进程

day 32 multiprocessing 模块中 Process 方法,僵尸进程,孤儿进程,守护进程

multiprocess 模块

仔细说来,multiprocess 不是一个模块而是 python 中一个操作、管理进程的包。 之所以叫 multi 是取自 multiple 的多功能的意思,在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆,我将这部分大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。

 

 

进程的 pid 父进程的 ppid

import time
import os
a = 1
b = 2
print(''子进程:'',os.getpid())   #python解释器
print(''父进程:'',os.getppid())  #pycharm软件
time.sleep(20)
print(a + b)

 

 创建进程的两种方式

#方法一
#大多数都使用方法一创建一个子进程
from multiprocessing import Process

def task(n):    #task 固定写法
    print("开始创建进程.............",n)

#windows环境下想开启子进程一定要 __name__ == ''__main__''
if __name__ == ''__main__'':
    p = Process(target=task,args=(1,),kwargs={"n":1})   #task 固定写法,创建对象时"task"不能加"()",args表示位置参数的,kwargs表示关键字参数
    p.start() #起动一个子进程



#方法2 class MyProcess(Process): #类的写法主要是直接继承"Process" 这个类. def __init__(self,n): super().__init__() #必须先要执行父类的 __init__属性,也就是"Process",要不然会报错 self.n = n def run(self): #子进程的代码全部都要写在这里面 a = 1 b = 2 print("%s is runing" % self.n) if __name__ == ''__main__'': p = MyProcess("alex") p.start() print("我是主")

 

 验证进程间的内存隔离

from multiprocessing import Process
import  time

x = 1000

def task():
    time.sleep(2)
    global x
    x = 2
    print("子进程:",x)

if __name__ == ''__main__'':
    p = Process(target=task,)
    p.start()
    time.sleep(5)
    print("主:",x)

 

 

主进程在子程序运行完之后运行

from multiprocessing import Process
def task(n):
    print("我是子进程开始运行了.......",n)
    time.sleep(5)
    print("子进程运行结束")

if __name__ == ''__main__'':
    p = Process(target=task,args=(1,),name="子进程")   #默认参数不变写法 args=(1,) 后面必须有逗号 name定义子进程的名字
    p.start()
    p.join()   #join 上面的子进程运行完毕之后运行主进程
    print("我是主进程")

 

 

 在一个主进程开启多个子进程

def task(n):
    print(''%s is begin'' % n)
    time.sleep(3)
    print(''%s is over'' % n)

def main():
    print(''主进程执行.....'')

if __name__ == ''__main__'':
    p1 = Process(target=task,args=(''p1'',))
    p2 = Process(target=task,args=(''p2'',))
    p3 = Process(target=task,args=(''p3'',))

    p1.start()  # 发送一个请求
    p2.start()  # 发送一个请求
    p3.start()  # 发送一个请求
    main()

 

 for 循环创建子进程

from multiprocessing import Process
import time

def task(n):
    print("%s 开始运行" % n)
    time.sleep(3)
    print("%s 运行结束了" % n)

if __name__ == ''__main__'':
    for i in range(1,4):
        p = Process(target=task,args=("p%s" % i,))
        p.start()

 

子进程和主进程的运行顺序 "串行" 和 "并发"

 

串行消耗时间长,并发消耗时间短

##串行##
from multiprocessing import Process
import time

def task(n):
    print(''%s is begin'' % n)
    time.sleep(3)
    print(''%s is over'' % n)

def main():
    print(''主进程执行.....'')

if __name__ == ''__main__'':
    # 创建三个进程对象

    p1 = Process(target=task, args=(''p1'',))
    p2 = Process(target=task, args=(''p2'',))
    p3 = Process(target=task, args=(''p3'',))
    start_time = time.time()
    # 发起三个请求
    p1.start()
    p1.join()   # 高速我的主进程,你要在我执行完毕之后在运行
    # print(111)
    p2.start()
    p2.join()
    p3.start()
    p3.join()
#     # 如果你要按照上面的写法:串行.
    print(time.time() - start_time)
    main()



##并发##
from multiprocessing import Process
import time

def task(n):
    print(''%s is begin'' % n)
    time.sleep(n)
    print(''%s is over'' % n)

def main():
    print(''主进程执行.....'')

if __name__ == ''__main__'':
    # 创建三个进程对象

    p1 = Process(target=task, args=(1,))
    p2 = Process(target=task, args=(2,))
    p3 = Process(target=task, args=(3,))
    start_time = time.time()
    # 发起三个请求

    p1.start()
    p2.start()
    p3.start()

    p1.join()  # 1
    p2.join()  # 2
    p3.join()  # 3
    print(time.time() - start_time)
    main()

 

 for 循环实现主程序等待等待所有子程序结束之后再运行

from multiprocessing import Process
import time

def task(n):
    print("%s开始运行" % n)
    # time.sleep(3)
    print("%s运行结束" % n)

if __name__ == ''__main__'':
    lst = []
    for i in range(1,4):
        p = Process(target=task,args=("p%s" % i,))
        p.start()
        p.join() #这里使用join是为了让数字顺序拼接上"1,2,3","p1开始运行,p2开始运行,p3开始运行"
        lst.append(p)   #  把子进程添加到列表内不让在外部执行,如果不添加到列表内在外执行之后就变成了串行.

        for c in lst:  # 拿到列表内的子进程
            c.join()   #通过join执行下面的主程序
    print("我是主程序")

总结:
    1,多个进程使用join,他们之间互不影响.
     p.join() 会将除join方法以外的方法视为主进程的方法(视为串行). 比如:p.start

 

 

 进程和对象的其他参数

from multiprocessing import Process
import time
import os
def task(n):
    print(''%s is begin'' % n)
    # print(os.getpid())
    print(''子进程:'', os.getpid(), ''主:'', os.getppid())
    time.sleep(3)
    print(''%s is over'' % n)

def main():
    print(''主进程执行.....'')

# if __name__ == ''__main__'':
    # p1 = Process(target=task, args=(''p1'',),name=''紫禁城'') # 自定制别名
    # p2 = Process(target=task, args=(''p2'',))
    # p1.start()
    # p2.start()
    # print(p1.name)  # 为进程起别名
    # print(p2.name)
    # p1.start()  # 给操作系统发送请求
    # p1.terminate() # 杀死进程
    # # time.sleep(3)
    # # p1.join()
    # time.sleep(1)
    # print(p1.is_alive())  # 判断进程死活
    # 判断id

    # p1 = Process(target=task,args=(1,))
    # p1.start()
    # # print(''子进程:'',p1.pid)  # 获取p1进程pid
    # print(''子进程:'',p1.pid,''主:'',os.getpid())

 

 

 僵尸进程和孤儿进程

僵尸进程一般针对 linux 系统,当一个主进程中的子进程在运行完毕之后,就会产生僵尸进程,但是 liux 底层有垃圾回收机制 (waitpid, 内核层面), 会默认将僵尸进程回收,如果主进程产生了大量的子进程回收不及时可能会影响的系统性能.

僵尸进程: 占有一点空间,保存 pid, 运行时间,状态,僵尸进程的回收是由主进程发起的.

孤儿进程: 当你的主进程意外挂了,就会形成孤儿进程,孤儿进程就会交给 linux 系统来处理.

 

 守护进程

守护进程会等待主进程的代码结束之后就立即结束

守护进程也是一个子进程,主进程永远要在子进程结束之后才能使用,因为主进程要负责回收子进程

from multiprocessing import Process
import time

def task(n):
    print(''%s is begin'' % n)
    time.sleep(3)
    print(''%s is over'' % n)

def main():
    print(''主进程执行.....'')

if __name__ == ''__main__'':
    # 创建三个进程对象

    p1 = Process(target=task, args=(''p1'',))
    p1.daemon = True # 你的p1进程就设置成了守护进程,便不会再执行p1的内容了.
    p1.start()
    time.sleep(2)
    main()

 

multiprocessing.process的用法

multiprocessing.process的用法

[TOC]

multiprocessing模块

仔细说来,multiprocess不是一个模块而是python中一个操作、管理进程的包。 之所以叫multi是取自multiple的多功能的意思,在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆,我将这部分大致分为四个部分:创建进程部分,进程同步部分,进程池部分,进程之间数据共享。

multiprocessing.Process模块

process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。

process模块介绍

Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)

强调:

  1. 需要使用关键字的方式来指定参数
  2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

参数介绍:

  • group参数未使用,值始终为None
  • target表示调用对象,即子进程要执行的任务
  • args表示调用对象的位置参数元组,args=(1,2,''egon'',)
  • kwargs表示调用对象的字典,kwargs={''name'':''egon'',''age'':18}
  • name为子进程的名称

方法介绍

  • p.start():启动进程,并调用该子进程中的p.run()
  • p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
  • p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
  • p.is_alive():如果p仍然运行,返回True
  • p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程

3.2 属性介绍

  • p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
  • p.name:进程的名称
  • p.pid:进程的pid
  • p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
  • p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

3.3 在windows中使用process模块的注意事项

在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),在创建子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。因此如果将process()直接写在文件中就会无限递归创建子进程报错。所以必须把创建子进程的部分使用if __name__ ==''__main__ 判断保护起来,import 的时候,就不会递归运行了。

Process的用法

一、jion用法

内部会调用wait(),等待执行完毕,回收pid

1.1 jion用法1

from multiprocessing import Process

import time

def foo():
    print(''process start'')
    time.sleep(2)
    print(''process end'')

if __name__ == ''__main__'':
    p = Process(target=foo) #创建子进程
    p.start()#给操作系统发指令,开启子进程
    time.sleep(5)
    p.join()#阻塞住主进程再等待子进程结束,然后再往下执行,(了解的是:内部会待用wait())
    print(''主进程'')


# 
process start
process end
主进程

1.2join用法2

from multiprocessing import Process
import time
def foo(x):
    print(''Process start'')
    time.sleep(x)
    print(''Process end'')
if __name__ == ''__main__'':
    p1 = Process(target=foo,args=(1,)) #进程传参的固定模式
    p2 = Process(target=foo,args=(2,))
    p3 = Process(target=foo,args=(3,))
    start = time.time()
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    end = time.time()
    print(end-start)
    print(''主进程'')
#进程是同时开启的,不确定是哪一个先开启,并且创建子进程需要时间,因此是3秒多
Process start
Process start
Process start
Process end
Process end
Process end
3.136319160461426
主进程

join用法2,优化

from multiprocessing import Process

import time
def foo(x):
    print(f''process{x},start'')
    time.sleep(x)
    print(f''process{x},end'')
if __name__ == ''__main__'':
    strart = time.time()
    p_list = []
    for i in range(1,4):
        p=Process(target=foo,args=(i,))
        p.start()
        p_list.append(p)
    print(p_list)
    for p in p_list:
        p.join()
    end = time.time()
    print(end-strart)
    print(''主进程'')
    
   # 
[<Process(Process-1, started)>, <Process(Process-2, started)>, <Process(Process-3, started)>]
process1,start
process2,start
process3,start
process1,end
process2,end
process3,end
3.1335043907165527
主进程

1.3 join用法3

from multiprocessing import Process
import time
def foo(x):
    print(f''process{x},start'')
    time.sleep(x)
    print(f''process{x},end'')

if __name__ == ''__main__'':
    p1 = Process(target=foo,args=(1,))
    p2 = Process(target=foo,args=(2,))
    p3 = Process(target=foo,args=(3,))
    start = time.time()
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    end = time.time()
    print(end-start)
    print(''主进程结束'')
#由于每一个进程都是在执行完后才会执行下一个进程,因此,时间是多余6s,创建子进程空间是需要时间的
process1,start
process1,end
process2,start
process2,end
process3,start
process3,end
6.339004039764404
主进程结束

二、查询进程的pid

进程的pid,相当于人的id身份证一样

from multiprocessing import Process,current_process
import os
import time

def task():
    print(''子进程 start'')
    print(''在子进程中查询自己的pid>'',current_process().pid)
    print(''在子进程中查询父进程的pid>'',os.getppid())
    time.sleep(200)
    print(''子进程end'')
if __name__ == ''__main__'':
    p = Process(target=task)
    p.start()
    print(''在主进程中查看子进程的pid>'',p.pid)#一定要写在start之后,在给操作系统发送开启子进程之后
    print(''主进程的pid>'',os.getpid())
    print(''主进程的父进程的pid>'',os.getppid())
    print(''主进程'')
    
###
在主进程中查看子进程的pid> 11112
主进程的pid> 7320
主进程的父进程的pid> 2464
主进程
子进程 start
在子进程中查询自己的pid> 11112
在子进程中查询父进程的pid> 7320

三,查询进程名name

from multiprocessing import Process,current_process
import time
def foo():
    print(''process start'')
    print(''子进程的名字'',current_process().name)
    time.sleep(2)
    print(''process end'')
if __name__ == ''__main__'':
    p = Process(target=foo)
    p2 = Process(target=foo)
    p3 = Process(target=foo,name=''ocean'')

    p.start()
    p2.start()
    p3.start()
    print(p.name)
    print(p2.name)
    print(p3.name)
    print(''主进程'')
################
Process-1
Process-2
ocean
主进程
process start
子进程的名字 Process-1
process start
子进程的名字 Process-2
process start
子进程的名字 ocean
process end
process end
process end

四、判断进程的生死is_alive()

from multiprocessing import Process
import time
def foo():
    print(''process start'')
    time.sleep(2)
    print(''process end'')
if __name__ == ''__main__'':
    p = Process(target=foo)
    p.start()
    print(p.is_alive())#True,进程开启,进程或者
    time.sleep(5)
    print(p.is_alive())#False 代码运行完毕,进程死亡(系统判定,实际情况在具体分析)
    print(''主进程'')
    
    
##############
True
process start
process end
False
主进程

五、杀死进程terminate()

from multiprocessing import Process
import time
def foo():
    print(''process start'')
    time.sleep(10)
    print(''process end'')
if __name__ == ''__main__'':
    p = Process(target=foo)
    p.start()
    p.terminate()#给操作系统发送一个请求,杀死进程的请求
    print(p.is_alive())
    p.join()
    print(p.is_alive())
    print(''主进程'')
###############
True
False
主进程

六、通过继承Process类开启进程

import os
from multiprocessing import Process


class MyProcess(Process):
    def __init__(self,name):
        # super(MyProcess,self).__init__()
        super().__init__()
        self.name=name
    def run(self):
        print(os.getpid())
        print(''%s 正在和女主播聊天'' %self.name)
if __name__ == ''__main__'':

        p1=MyProcess(''wupeiqi'')
        p2=MyProcess(''yuanhao'')
        p3=MyProcess(''nezha'')

        p1.start() # start会自动调用run
        p2.start()
        # p2.run()
        p3.start()


        p1.join()
        p2.join()
        p3.join()

        print(''主线程'')
        
####################
1516
wupeiqi 正在和女主播聊天
4864
yuanhao 正在和女主播聊天
18228
nezha 正在和女主播聊天
主线程

七、进程间的数据隔离问题

from multiprocessing import Process
def work():
    global n
    n = 0
    print(''子进程内:'',n)
if __name__ == ''__main__'':
    n = 100
    p = Process(target=work)
    p.start()
    print(''主进程内:'',n)
##############
主进程内: 100
子进程内: 0


parallel.futures中的ProcessPoolExecutor比multiprocessing.Pool慢

parallel.futures中的ProcessPoolExecutor比multiprocessing.Pool慢

我是用新的闪亮试验concurrent.futures在Python
3.2模块引起,而我注意到,几乎相同的代码,使用泳池从concurrent.futures的 方式
比使用慢multiprocessing.Pool。

这是使用多重处理的版本:

def hard_work(n):    # Real hard work here    passif __name__ == ''__main__'':    from multiprocessing import Pool, cpu_count    try:        workers = cpu_count()    except NotImplementedError:        workers = 1    pool = Pool(processes=workers)    result = pool.map(hard_work, range(100, 1000000))

这是使用current.futures:

def hard_work(n):    # Real hard work here    passif __name__ == ''__main__'':    from concurrent.futures import ProcessPoolExecutor, wait    from multiprocessing import cpu_count    try:        workers = cpu_count()    except NotImplementedError:        workers = 1    pool = ProcessPoolExecutor(max_workers=workers)    result = pool.map(hard_work, range(100, 1000000))

使用从Eli Bendersky文章中获得的简单分解函数,这些就是我计算机(i7、64位,Arch Linux)上的结果:

[juanlu@nebulae]─[~/Development/Python/test]└[10:31:10] $ time python pool_multiprocessing.pyreal    0m10.330suser    1m13.430ssys 0m0.260s[juanlu@nebulae]─[~/Development/Python/test]└[10:31:29] $ time python pool_futures.pyreal    4m3.939suser    6m33.297ssys 0m54.853s

我无法使用Python探查器对它们进行探查,因为出现泡菜错误。有任何想法吗?

答案1

小编典典

使用mapfrom时concurrent.futures,来自iterable的每个元素将分别提交给执行程序,该执行程序Future将为每个调用创建一个对象。然后,它返回一个迭代器,该迭代器产生期货返回的结果。
Future对象相当重,它们需要做很多工作才能允许它们提供的所有功能(例如回调,取消功能,检查状态等)。

与此相比,multiprocessing.Pool开销要少得多。它分批提交作业(减少IPC开销),并直接使用该函数返回的结果。对于大批量的工作,多处理绝对是更好的选择。

如果您希望对那些开销不那么重要的长期运行的工作进行汇总,希望通过回调通知您或不时检查它们是否完成或能够单独取消执行,则期货是很好的选择。

个人说明

我真的想不出使用什么理由Executor.map-它没有提供任何期货功能-
除了可以指定超时的功能。如果您只是对结果感兴趣,最好使用multiprocessing.Pool的map函数之一。

关于multiprocessing.Process使用spawn方法:继承了哪些对象?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于(并发编程)进程 (multiprocessing--Process实现进程并发)、day 32 multiprocessing 模块中 Process 方法,僵尸进程,孤儿进程,守护进程、multiprocessing.process的用法、parallel.futures中的ProcessPoolExecutor比multiprocessing.Pool慢的相关信息,请在本站寻找。

本文标签: