Python進階----進程間數據隔離, join阻塞等待, 進程屬性, 殭屍進程和孤兒進程, 守護進程

Python進階----進程間數據隔離, join阻塞等待, 進程屬性, 殭屍進程和孤兒進程, 守護進程

一丶獲取進程以及父進程的pid

含義:

   進程在內存中開啓多個,操做系統如何區分這些進程,每一個進程都有一個惟一表示python

方法三種方法:

    一,終端查看全部pid tasklistlinux

    二,指定具體的PID tasklist | findstr python
    三,代碼查看pid os 模塊微信

### 利用os 模塊 查看 pid(當前進程id)  和 ppid(父進程id)

import os
import time
print('子進程pid:',os.getpid())  # 查看當前python程序的pid
print('父進程pid:',os.getppid()) #pycharm的pid
time.sleep(100)

二丶驗證進程之間的數據隔離

驗證數據隔離

    若是主進程中x的值是否改變,沒有改變則說明父進程與子進程之間數據隔離app

爲何進程之間數據不能共享.

    開啓兩個程序 一個QQ,一個微信, 開啓了兩個進程.若是進程之間能夠通訊, 那QQ的進程是否是能夠任意訪問微信的數據. 這樣會形成諸多問題. 因此,進程間理論上是不能通訊的. 可是能夠藉助中間代理(隊列)操作系統

# -*-coding:utf-8-*-
# Author:Ds
from multiprocessing import Process
x=1000
def task():
    global x  #  引用成全局變量
    x=2       #  修改全局變量( 因爲數據隔離,修改的數據只存在子進程中)


if __name__ == '__main__':
    p1=Process(target=task,)
    p1.start()
    
    # 若是x的值沒有改變,說明父進程與子進程之間數據隔離
    print(f'主進程中的x的變量:{x}')

驗證數據延用

    只有數字能被沿用,範圍:-5~256, 主進程子進程是沿用同一個.字符串等其餘數據類型不延用線程

# -*-coding:utf-8-*-
# Author:Ds
from multiprocessing import Process
import time
x=100
def task():
    print(f'子進程中:{id(x)}')

if __name__ == '__main__':
    # 子進程與父進程之間的空間隔離., 要驗證初始變量是不是一個id.
    print(f'主進程中:{id(x)}')
    p1=Process(target=task,)
    p1.start()
    time.sleep(3)

三丶join方法

含義:

    join進程等待,等待主進程等待子進程結束以後再執行.不會被夯住(不會卡住)代理

###  並行 , 一共執行3秒. (前提是你已經建立3個子進程)
 #緣由:1. start方法 只是告訴主進程, 開啓一個子線程.
     # 2. join方法是等待
from multiprocessing import  Process
import time
def task(name,sec):
    print(f'{name}is running')
    time.sleep(sec)
    print(f'{name} is done')

    
if __name__ == '__main__':
    start_time=time.time()   #記錄程序開始運行時間

    p1=Process(target=task,args=('alex',1))
    p2=Process(target=task,args=('abc',2))
    p3=Process(target=task,args=('ds',3))
    
    # 如今內存中幾乎同時建立了3個子進程
    # 隨機性,建立子線程時間可能不一樣.  操做系統調用cpu先運行誰,誰先執行.
    p1.start()  
    p2.start()
    p3.start()
    
    ### 至關於: 如今內存中存在3個任務,同時進行,第一個任務執行1秒停頓, join方法,. 第二個任務已經執行了1秒,再執行1秒.over.第三個任務已經執行2秒停頓.再執行1秒.over.
    
   
    p1.join()   # 通知cpu 等待子進程執行完就執行主進程
    p2.join()   # 通知cpu 等待子進程執行完就執行主進程
    p3.join()   # 通知cpu 等待子進程執行完就執行主進程
    ### 以最時間長的爲標準. 執行完子進程再執行父進程的打印. 
    
    print(f'執行總時長:{time.time()-start_time}')
    
    
 ### 總結:  三次start開啓了三個通道.同時進行join 只是通知cpu要等待子進程執行完畢,再執行主進程





### for循環簡化上述代碼:  

from multiprocessing import  Process
import time

def task(name,sec):
    print(f'{name}is running')
    time.sleep(sec)
    print(f'{name} is done')

     
if __name__ == '__main__':
    start_time=time.time()
    p_l=[]   # 把子線程對象,放在列表中
    for e in range(1,4):
        e=Process(target=task,args=('alex',3))
        e.start()
        p_l.append(e)
    for i in p_l:
        i.join()
    print(f'{time.time()-start_time}')
### join 串行
from multiprocessing import  Process
import time
def task(name,sec):
    print(f'{name} is running')
    time.sleep(sec)
    print(f'{name} is done')

if __name__ == '__main__':
    start_time=time.time()

    p1=Process(target=task,args=('alex',1))
    p2=Process(target=task,args=('abc',2))
    p3=Process(target=task,args=('ds',3))

    p1.start()  # 先建立p1 子進程並執行
    p1.join()   # 通知cpu 等待子進程執行完畢,再執行主進程

    p2.start()  # 等待p1執行完畢在開啓p2進程
    p2.join()

    p3.start()  # 等待p1.p2執行完畢在開啓p3進程
    p3.join()
    
    # 最少6秒,還有系統調度cpu建立進程時間,每每高於6秒
    print(f'執行總時長:{time.time()-start_time}')
    
    
### 總結:  一次 start 一次 join  至關於開了一個通道. 只能一次過以一輛車. join通知cpu等待子進程完成後才能繼續執行主進程

四丶進程對象的其餘屬性

常見的屬性:

    pid:獲取子進程idcode

    name:獲取子進程name屬性對象

    terminate:殺死子進程隊列

    is_alive:查看子進程是否還活着

# -*-coding:utf-8-*-
# Author:Ds

from multiprocessing import Process
import time

def task():
    print('子線程 is running')

if __name__ == '__main__':
    p=Process(target=task,name='任務1')
    p.start()

    print(p.pid) # 獲取子進程的pid
    print(p.name) # 獲取子進程的name屬性
        
    p.terminate()   # 殺死進程  :通知操做系統執行當前任務(耗時)
    time.sleep(1)   # 因爲is_alive存在主進程中.因此須要睡1秒以後再進行查看
    
    print(p.is_alive())
    print('主進程')

五丶殭屍進程與孤兒進程(存在Linux系統中)

進程瞭解:

   每一個進程退出時,內核釋放應該進程全部的資源,可是還會保留一部分的信息,如:進程號,進程狀態,運行時間.直到主進程利用這個waitepid()方法,纔可以徹底釋放,回收子進程的資源

殭屍進程:(有害)

   主進程(父進程)不能正常的使用waitepid()方法對子進程進行資源回收,這個狀態是殭屍狀態(Z狀態).那麼這部分的子進程就會成爲殭屍進程

   每一次子進程結束前,都會有一個殭屍狀態.直到父進程調用waitepid()纔會從殭屍態到消亡態

殭屍進程的害處:

   殭屍進程的資源沒法被釋放,長期佔用.內存壓力增大.當新的程序來處理時,則會由於資源不足而致使運行失敗.

   kill -9 pid 是殺不死殭屍進程的,他能將進程的狀態從正在運行態變成殭屍態,卻不能將殭屍態的進程變爲消亡態

# -*-coding:utf-8-*-
# Author:Ds

#### 父進程不能給子進程收屍 ,子進程就是殭屍進程

from multiprocessing import Process
import time
import os

def task(name):

    print(f'{name} is running')
    print(f'子進程開始了:{os.getpid()}')
    time.sleep(50)


if __name__ == '__main__':
    for i in range(100000):
        p = Process(target=task,args=('懟哥',))
        p.start()
    print(f'\033[1;35;0m 主進程:{os.getpid()}\033[0m')

孤兒進程:

   父進程已經掛掉了,子進程還在運行.這個子進程就是孤兒進程. 孤兒進程會被'init'進程回收

from multiprocessing import Process
import time
import os

def task(name):

    for i in  range(20):
        time.sleep(0.5)
        print(f'子進程開始了:{os.getpid()}')


if __name__ == '__main__':
    p = Process(target=task,args=('懟哥',))
    p.start()
    time.sleep(3)
    print(f'\033[1;35;0m 主進程:{os.getpid()}\033[0m')
  

# 父進程 正常對退出,子進程還有本身的事情沒有幹完. 因此子進程成爲孤兒進程

六丶守護進程

含義:

   守護進程自己是一個子進程,守護的主進程

   結束條件:主進程代碼結束了,守護進程也就結束了

### 守護進程也屬於子進程,主進程代碼結束前結束.由於主進程要回收子進程的資源

# 1. 主進程的代碼結束,守護進程結束

# 2. 主進程要回收守護進程(子進程)的資源

# 3. 等待其餘全部子進程結束

# 4. 主進程回收全部子進程資源
# -*-coding:utf-8-*-
# Author:Ds
from multiprocessing import Process
import time
import os

def task(name):

    for i in  range(20):
        time.sleep(0.5)
        print(f'子進程開始了:{os.getpid()}')


def func2():
    print('start:func2')
    time.sleep(5)
    print('end:func2')

if __name__ == '__main__':
    start_time=time.time()
    p = Process(target=task,args=('懟哥',))
    p.daemon=True #  設置爲守護進程
    p.start()
    Process(target=func2).start()
    print('in main')
    time.sleep(3)
    print(f'主進程開始了:{os.getpid()}  ,結束時間{time.time()-start_time}')
    


###  一個py文件至關於開啓了一個進程 ,這是一個主進程.
    # 主進程會等待全部的非守護進程運行完畢才結束哦  --->?爲何?  由於主進程要對全部的子進程進行資源回收
    #  守護進程守護是什麼? 是主進程的'代碼運行完畢'. 守護進程就結束了.
    #  我的理解: 主進程會等待全部的非守護進程的子進程執行完畢. 連同守護進程的資源統一回收.
##################################################################################################

### 爲何要有主進程等待子進程結束以後才結束呢?
    # 1.由於主進程負責給子進程回收一些系統資源

### 守護進程:自己是一個子進程,守護的主進程
    # 結束條件:主進程代碼結束了,守護進程也就結束了

### 進程
    # 主進程的代碼結束,守護進程結束
    # 主進程要回收守護進程(子進程)的資源
    # 等待其餘全部子進程結束
    # 主進程回收全部子進程資源
相關文章
相關標籤/搜索