python 之 併發編程(開啟子進程的兩種方式,進程對象的屬性)

第九章併發編程

同一個程序執行多次是多個進程

import time
import os
​
print('爹是:',os.getppid())      #父進程PID,(pycharm)
print('me是: ',os.getpid())      #3748 14648
time.sleep(500)

9.1 開啟子進程的兩種方式

服務端目標: 1、不間斷地提供服務 2、服務端要支持高併發+高性能

一個進程在運行過程中開啟了子進程(如nginx開啟多進程,os.fork,subprocess.Popen等)

父進程發起請求,操作系統創建子進程

方式一:

from multiprocessing import Process
import time
import os
def task(name):
    print('%s is running' %name)
    time.sleep(3)
    print('%s has done' %name)
    print('爹是:', os.getppid()) #me是:  13892
    print('me是: ', os.getpid())  #me是:  7492
if __name__ == '__main__':                  # windows系統,開啟子進程的操作一定要放到這下面
    p=Process(target=task,args=('egon',))     # p=Process(target=task,kwargs={'name':'egon'})
    p.start() # 向操作系統發送請求,操作系統會申請內存空間,然後把父進程的數據拷貝給子進程,作為子進程的初始狀態
    print('me是: ', os.getpid())  #me是:  13892
    print('======主')#======主 egon is running egon has done
  • target 表示調用對象,即子進程要執行的任務

  • args 指定為target函數傳位置參數,是一個元組形式,必須有逗號

  • kwargs 表示調用對象的字典,kwargs={‘name’:’egon’,’age’:18}

  • p.start() 啟動進程,並調用該子進程中的p.run()

方式二:

from multiprocessing import Process
import time
​
class MyProcess(Process):
    def __init__(self,name):
        super(MyProcess,self).__init__()
        self.name=name
​
    def run(self):
        print('%s is running' %self.name)
        time.sleep(3)
        print('%s has done' %self.name)
​
if __name__ == '__main__':
    p=MyProcess('egon')
    p.start()
    print('')  #主  egon is running  egon has done
  • p.run():進程啟動時運行的方法,正是它去調用target指定的函數,我們自定義類的類中一定要實現該方法

9.2 進程之間內存空間隔離

from multiprocessing import Process
import time
x=1000
def task():
    time.sleep(3)
    global x
    x=0
    print('兒子死啦',x)
​
​
if __name__ == '__main__':
    print(x)
    p=Process(target=task)
    p.start()
    time.sleep(5)
    print(x)    #1000    兒子死啦 0    1000

9.3 父進程等待子進程結束

from multiprocessing import Process
import time
x=1000
def task():
    time.sleep(3)
    global x
    x=0
    print('兒子死啦',x)
​
if __name__ == '__main__':
    p=Process(target=task)
    p.start()
​
    p.join() # 讓父親在原地等
    print(x)
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:                       #1 is runing
        p.join()                        #3 is runing
    print('',(time.time() - start_time)) #2 is runing    主  3.112313

9.4 進程對象的其他屬性

  • p.terminate():強制終止進程p,不會進行任何清理操作,如果p創建了子進程,該子進程就成了殭屍進程,使用該方法需要特別小心這種情況。如果p還保存了一個鎖那麼也將不會被釋放,進而導致死鎖

  • p.is_alive():如果p仍然運行,返回True

  • p.join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,而p是處於運行的狀態)。timeout是可選的超時時間,強調: p.join只能 join住start開啟的進程,而不能join住run開啟的進程

  • p.pid:進程的pid

from multiprocessing import Process
import time,os
x=1000
def task(n):
    print('%s is runing self:%s parent:%s' %(n,os.getpid(),os.getppid()))#self:13032 parent:9136
    time.sleep(3)
​
if __name__ == '__main__':
    p1=Process(target=task,args=(1,),name='任務1')#不指定name,p1.name是process-1
    p1.start()
          
    print(p1.pid)       # 13032 沒有p1.ppid
    print(p1.name)      # 任務1
    p1.terminate()      # 向操作系統提交進程終止 
    p1.join()
    print(p1.is_alive()) # False
print('',os.getpid())# 主 9136
点赞

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *