Python 第三十三章 進程進階 進程建立+空間隔離+其餘參數+守護進程+殭屍進程和孤兒進程

進程建立的兩個方式

# 開啓進程的第一種方式:永遠先執行主進程的代碼

# 多線程模塊導入進程
from multiprocessing import Process
# 導入時間模塊
import time
# 定義一個task函數,name函數
def task(name):
    """
    主進程
    :param name:
    :return:
    """
    # 輸出xx is running
    print(f'{name} is running')
    # 睡2秒
    time.sleep(2)
    # 輸出xx is gone
    print(f'{name} is gone')

# 在本模塊執行此方法
if __name__ == '__main__':
# 在Windows環境下,開啓進程必須在__name__ == '__main__'下面

    # 開啓子進程的命令
    # 建立一個進程對象p target=task目標是task函數,args=('zs',) 給name賦值zs
    p = Process(target=task,args=('zs',)) # 元祖的形式
    # 開啓一個子進程 start() 開啓命令
    p.start() # 子進程會copy主進程的初始資料 至關於同時開啓子進程和主進程
    # 這個信號操做系統接收到以後,會在內存中開闢一個子進程空間,而後再將主進程上全部數據copy加載到子進程,
    # 而後再去調用cpu去執行

    # 執行主進程
    print('主程序-開始') # 只運行主進程和子進程,先執行主進程,開闢進程會很消耗內存
    # 輸出:
    # 主程序-開始
    # zsis running
    # zsis gone
    # 睡3秒
    time.sleep(3)
    print('主進程-結束')
    # 輸出:
    # 主程序-開始
    # zs is running
    # zs is gone
    # 主進程-結束


# 開啓進程的第二種方式:需重構父類
from multiprocessing import Process
import time

# 若是不進行實例化.name屬性默認有傳參,屬性值爲MyProcess1
# 建立一個類MyProcess 繼承Process
class MyProcess(Process):

    # 直接實例化會報錯 須要重構父類 先執行父類的run再執行本身的run
    # 實例化對象
    def __init__(self,name):
        # supper()重構父類
        super().__init__()
        # 屬性值爲name=屬性名name
        self.name = name

    # 定義一個run方法 實例化
    def run(self):
        # 輸出xx is running
        print(f'{self.name} is running')
        # 睡2秒
        time.sleep(2)
        # 輸出xx is gone
        print(f'{self.name} is gone')
# 在本模塊執行此方法
if __name__ == '__main__':
    # 實例化對象p 把zs給name
    p = MyProcess('zs')
    # 啓動子進程
    p.start()
    print('主進程-開始')

# 簡單應用
from multiprocessing import Process
import time
def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone')
def task1(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')
def task2(name):
    print(f'{name} is running')
    time.sleep(3)
    print(f'{name} is gone')

# 串行執行一個進程中執行三個任務 4.5秒
if __name__ == '__main__':
    # 啓動時間=當前時間
    start_time = time.time()
    task('zs')
    task1('zs2')
    task2('zs3')
    # 當前時間-啓動時間=運行的時間
    print(f'結束時間{time.time()-start_time}')

    # 輸出
    # zs is running
    # zs is gone
    # zs2 is running
    # zs2 is gone
    # zs3 is running
    # zs3 is gone
    # 結束時間6.009660959243774

# 三個進程 併發或者並行的執行三個任務 3秒
if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=('zs',))
    p2 = Process(target=task1,args=('zs2',))
    p1.start()
    p2.start()
    task2('zs3')
    print(f'結束時間{time.time()-start_time}')
    # 輸出
    # zs3 is running
    # zs is running
    # zs2 is running
    # zs is gone
    # zs2 is gone
    # zs3 is gone
    # 結束時間3.009711742401123

進程的pid

# 導入os模塊
import os
# 導入time模塊
import time
# mac 命令行獲取全部的進程的pid號 ps-ef
# Windows 命令行獲取全部的進程的pid號 tasklist

# 代碼級別如何獲取一個進程pid號 os.getpid()
print(f'子進程:{os.getpid()}')
# 如何獲取父進程(主進程)的pid號 os.getppid()
print(f'主進程:{os.getppid()}')
time.sleep(5) # 睡50秒打開終端,找到Python進程的pid進行覈對

from multiprocessing import Process
import time
import os
def task(name): # 再執行子進程
    print(f'子進程{os.getpid()}')
    print(f'主進程{os.getppid()}')

if __name__ == '__main__':
    # 建立一個進程對象
    p = Process(target=task,args=('zs',))
    p.start()
    print(f'主進程的pid{os.getppid()}') # 先執行主進程
    # 輸出:
    # 子進程:6712
    # 主進程:590
    # 主進程的pid590
    # 子進程6713
    # 主進程6712

空間隔離

# 怎麼執行都是先執行主進程
# 加個sleep睡一會
# 空間隔離
# 子進程修改後的name與主進程的name沒有關係

from multiprocessing import Process
import os
import time

# 不可變
name = 'zs'
def task():
    global name
    name = 'ls'
    print(f'子進程{name}') # ls

if __name__ == '__main__':
    p = Process(target=task) # 建立一個進程對象
    p.start()
    time.sleep(3)
    print(f'主進程{name}') # zs
    # 輸出
    # 子進程ls
    # 主進程zs


# 可變的
lst = ['ww',]
def task():
    lst.append('yy')
    print(f'子進程{lst}') # ['ww','yy']

if __name__ == '__main__':
    p = Process(target=task) # 建立一個進程對象
    p.start()
    time.sleep(3)
    print(f'主進程{lst}') # ['ww']
    # 輸出
    # 子進程['ww', 'yy']
    # 主進程['ww']

進程的其餘參數

from multiprocessing import Process
import time


# 殺死子進程 terminate()
def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')

if __name__ == '__main__':
    p = Process(target=task,args=('zs',)) # 建立一個進程對象
    p.start() # 啓動進程
    p.terminate() # 殺死子進程
    print('主進程')
    # 輸出
    # 主進程
# 只輸出主進程,子進程被殺死

from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')


if __name__ == '__main__':
    p = Process(target=task, args=('zs',)) # 建立一個進程對象
    p.start() # 啓動進程
    time.sleep(1) # 睡1秒
    p.terminate()  # 殺死子進程
    print('主進程')
    # 輸出
    # zs is running
    # 主進程
# 先執行子進程睡一會,再殺死子進程,最後執行子進程

# 查看是否真的殺死子進程 子進程是否還活着is_alive()方法
from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')

if __name__ == '__main__':
    p = Process(target=task,args=('zs',)) # 建立一個進程對象
    p.start() # 啓動子進程
    p.terminate() # 殺死子進程
    p.join() # 阻塞 還能夠用sleep()
    print(p.is_alive()) # 判斷子進程是否還活着 True活着 False死了
    print('主進程')
    # 輸出
    # False
    # 主進程


# 增長屬性 默認name屬性 Process屬性值
from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')

if __name__ == '__main__':
    p = Process(target=task,args=('zs',),name ='alex') # 建立一個進程對象
    p.start() # 啓動子進程
    p.name = 'ls' # 添加屬性
    print(p.name) # 打印name :ls
    print('主進程')
    # 輸出:ls
    # 主進程
    # zs is running
    # zs is gone

守護進程

# 守護進程
# 子進程守護者主進程,只要主進程結束,子進程跟着結束 daemon=True
from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is gone')

if __name__ == '__main__':
    p = Process(target=task,args=('zs',)) # 建立一個進程對象p
    # 將p子進程設置成守護進程,只要主進程結束,守護進程立刻結束
    p.daemon = True # 在開啓子進程以前設置守護進程
    p.start()# 開啓子進程
    time.sleep(1) # 睡一會
    print('主進程')
    # 輸出
    # zs is running
    # 主進程

殭屍進程和孤兒進程

"""
# 殭屍進程 基於Unix環境(Linux,MacOs)
# 主進程等子進程完成以後,主進程再結束
# ***生命週期:
# 主進程時刻監測子進程的運行狀態,當子進程結束以後,一段時間以內,將子進程進行回收

# 爲何主進程不在子進程結束後立馬對其回收呢
# 1.主進程與子進程是異步關係,主進程沒法立刻捕獲子進程何時結束
# 2.若是子進程結束以後立刻在內存中釋放資源,主進程就沒有辦法監測子進程的狀態了

# ***Unix針對上面的問題,提供了一個機制
# 全部的子進程結束以後,立馬會釋放掉文件的操做連接,內存的大部分數據,
  可是會保留一個一些內容:進程號,結束時間,運行狀態,等待主進程監測,回收

# 殭屍進程:
# 全部的子進程結束以後,在被主進程回收以前,都會進入殭屍狀態

# 殭屍進程的危害:
# 若是父進程不對殭屍進程進行回收(wait/waitpid),產生大量的殭屍進程
  這樣就會佔用內存,佔用進程pid號

# 孤兒進程:
# 父進程因爲某種緣由結束了,可是子進程還在運行中,這樣這些子進程就變成了孤兒進程。
  父進程若是結束了,全部的孤兒進程就會被init進程的回收,init就變成了父進程

# 如何解決殭屍進程:
# 父進程產生了大量子進程,可是不回收,這樣就會造成大量的殭屍進程,
  解決方式就是直接殺死父進程,將全部的殭屍進程變成孤兒進程,進程由init進行回收

"""
from multiprocessing import Process
import time
import os
def task(name):
    print(f'{name} is running')
    print(f'主進程:{os.getppid()}')
    print(f'子進程:{os.getpid()}')
    time.sleep(50)
    print(f'{name} is gone')

if __name__ == '__main__':
    p = Process(target=task,args=('zs',))
    p.start()
    print('主程序-開始')
    time.sleep(3)
    print('主進程-結束')
相關文章
相關標籤/搜索