併發編程-進程-06開啓多進程

一丶multiprocess模塊

multiprocess是python中一個操做、管理進程的包。python

1.2建立多進程方法

multiprocess.process模塊是一個建立進程的模塊,藉助這個模塊,就能夠完成進程的建立。linux

"""
建立進程就是在內存中從新開闢一塊內存空間
將容許產生的代碼丟進去
一個進程對應在內存就是一塊獨立的內存空間

進程與進程之間數據是隔離的 沒法直接交互
可是能夠經過某些技術實現間接交互
"""

1.2 建立方法

Process([group [, target [, name [, args [, kwargs]]]]])`,由該類實例化獲得的對象,表示一個子進程中的任務(還沒有啓動)windows

強調:安全

  1. 須要使用關鍵字的方式來指定參數
  2. args指定的爲傳給target函數的位置參數,是一個元組形式,必須有逗號

1.3參數介紹:

  • group參數未使用,值始終爲None
  • target表示調用對象,即子進程要執行的任務
  • args表示調用對象的位置參數元組,args=(1,2,'egon',)
  • kwargs表示調用對象的字典,kwargs={'name':'egon','age':18}
  • name爲子進程的名稱

1.4方法介紹

  • 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開啓的進程

1.5 屬性介紹

  • p.daemon:默認值爲False,若是設爲True,表明p爲後臺運行的守護進程,當p的父進程終止時,p也隨之終止,而且設定爲True後,p不能建立本身的新進程,必須在p.start()以前設置網絡

    ps: 這個能夠在process建立對象時候後面加個參數 daemon=True也可!併發

  • p.name:進程的名稱app

  • p.pid:進程的piddom

  • p.exitcode:進程在運行時爲None、若是爲–N,表示被信號N結束(瞭解便可)socket

  • p.authkey:進程的身份驗證鍵,默認是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是爲涉及網絡鏈接的底層進程間通訊提供安全性,這類鏈接只有在具備相同的身份驗證鍵時才能成功(瞭解便可)函數

二丶注意事項

2.1windows中使用process的注意事項

在Windows操做系統中因爲沒有fork(linux操做系統中建立進程的機制),在建立子進程的時候會自動 import 啓動它的這個文件,而在 import 的時候又執行了整個文件。所以若是將process()直接寫在文件中就會無限遞歸建立子進程報錯。因此必須把建立子進程的部分使用if \_\_name\_\_ =='\_\_main\_\_' 判斷保護起來,import 的時候,就不會遞歸運行了

三丶建立進程代碼實現

3.1建立進程方式一

from multiprocessing import Process
import time


def test(name):
    print('%s is running'%name)
    time.sleep(3)
    print('%s is over'%name)

"""
windows建立進程會將代碼以模塊的方式 從上往下執行一遍
linux會直接將代碼完完整整的拷貝一份


windows建立進程必定要在if __name__ == '__main__':代碼塊內建立  不然報錯
"""
if __name__ == '__main__':
    p = Process(target=test,args=('egon',))  # 建立一個進程對象
    p.start()  # 告訴操做系統幫你建立一個進程
    print('主')

3.2建立進程方式二

# 建立進程的第二種方式
from multiprocessing import Process
import time

class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print('%s is running' % self.name)
        time.sleep(3)
        print('%s is over' % self.name)

if __name__ == '__main__':
    p = MyProcess('egon')
    p.start()
    print('主')

3.3join()方法使用案例

from multiprocessing import Process
import time

def test(name,i):
    print('%s is running'%name)
    time.sleep(i)
    print('%s is over'%name)
if __name__ == '__main__':
    p_list = []
    # for i in range(3):
    #     p = Process(target=test,args=('進程%s'%i,i))
    #     p.start()
    #     p_list.append(p)
    # for p in p_list:
    #     p.join()
    p = Process(target=test,args=('egon',1))
    p1 = Process(target=test,args=('kevin',2))
    p2 = Process(target=test,args=('jason',3))
    start_time = time.time()
    p.start()  # 僅僅是告訴操做系統幫你建立一個進程 至於這個進程何時創  操做系統隨機決定
    p1.start()
    p2.start()
    p2.join()
    p.join()
    p1.join()

    # 主進程代碼等待子進程運行結束 才繼續運行
    # p.join()  # 主進程代碼等待子進程運行結束
    print('主')
    print(time.time() - start_time)

四丶進程間數據隔離

from multiprocessing import Process
import time

money = 100

def test():
    global money
    money = 99999999

if __name__ == '__main__':
    p = Process(target=test)
    p.start()
    p.join()
    print(money)

五丶進程對象的部分方法

  1. os.getpid()獲取當前進程ID
  2. os.getppid()獲取父進程ID
  3. current_process().pid獲取當前進程ID ,推薦os的
  4. 進程對象.is_alive()判斷進程是否存活
from multiprocessing import Process,current_process
import os
import time


def test(name):
    # print('%s is running'%name,current_process().pid)
    print('%s is running'%name,'子進程%s'%os.getpid(),'父進程%s'%os.getppid())
    time.sleep(3)
    print('%s is over'%name)


if __name__ == '__main__':
    p = Process(target=test,args=('egon',))
    p.start()
    # p.terminate()  # 殺死當前進程  實際上是告訴操做系統幫你殺死一個進程
    time.sleep(1000)
    print(p.is_alive())  # 判斷進程是否存活
    # print('主',current_process().pid)
    p.join()
    print('主',os.getpid(),'主主進程:%s'%os.getppid())

六丶守護進程

會隨着主進程的結束而結束。

主進程建立守護進程

  其一:守護進程會在主進程代碼執行結束後就終止

  其二:守護進程內沒法再開啓子進程,不然拋出異常:AssertionError: daemonic processes are not allowed to have children

注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止。

from multiprocessing import Process
import time


def test(name):
    print('%s總管正常活着'%name)
    time.sleep(3)
    print('%s總管正常死亡'%name)


if __name__ == '__main__':
    p = Process(target=test,args=('egon',))
    p.daemon = True  # 將該進程設置爲守護進程   這一句話必須放在start語句以前 不然報錯
    p.start()
    time.sleep(0.1)
    print('皇帝jason壽正終寢')

p.daemon:默認值爲False,若是設爲True,表明p爲後臺運行的守護進程,當p的父進程終止時,p也隨之終止,而且設定爲True後,p不能建立本身的新進程,必須在p.start()以前設置

七丶socket多進程實現聊天併發

7.1服務端

from socket import *
from multiprocessing import Process

server=socket(AF_INET,SOCK_STREAM)
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1',8080))
server.listen(5)

def talk(conn,client_addr):
    while True:
        try:
            msg=conn.recv(1024)
            if not msg:break
            conn.send(msg.upper())
        except Exception:
            break

if __name__ == '__main__': # windows下start進程必定要寫到這下面
    while True:
        conn,client_addr=server.accept()
        p=Process(target=talk,args=(conn,client_addr))
        p.start()

7.2客戶端

from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))


while True:
    msg=input('>>: ').strip()
    if not msg:continue

    client.send(msg.encode('utf-8'))
    msg=client.recv(1024)
    print(msg.decode('utf-8'))

八丶殭屍進程和孤兒進程

  1. 父進程回收子進程資源的兩種方式
    1.join方法
    2.父進程正常死亡
    全部的進程都會步入殭屍進程

  2. 孤兒進程(無害的)
    子進程沒死 父進程意外死亡

    針對linux會有兒童福利院(init) 若是父進程意外死亡他所建立的子進程都會被福利院收養

ps:孤兒進程是無害的由於"有人"收留,可是殭屍進程確實有害的,它的存在會佔用pid,會致使最後無pid可用,會最終影響整個電腦的運行

相關文章
相關標籤/搜索