三. 併發編程 (程序中的進程操做)

一 .程序中的進程操做python

1. multiprocess模塊

仔細說來,multiprocess不是一個模塊而是python中一個操做、管理進程的包。 之因此叫multi是取自multiple的多功能的意思,在這個包中幾乎包含了和進程有關
的全部子模塊。因爲提供的子模塊很是多,爲了方便你們歸類記憶,我將這部分大體分爲四個部分:建立進程部分,進程同步部分,進程池部分,進程之間數據共享。

process模塊介紹

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

 2. 進程(參數 方法 屬性 注意事項)編程

參數說明
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開啓的進程 屬性介紹 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字符的字符串。這個鍵的用途是爲涉及網絡鏈接的底層進程間通訊提供安全性,這類鏈接只有在具備相同的身份驗證鍵時
才能成功(瞭解便可)
在windows中使用process模塊的注意事項 在Windows操做系統中因爲沒有fork(linux操做系統中建立進程的機制),在建立子進程的時候會自動
import 啓動它的這個文件,而在 import
的時候又執行了整個文件。所以若是將process()直接寫在文件中就會無限遞歸建立子進程報錯。因此必須把建立子進程的部分使用if __name__ ==‘__main__
判斷保護起來,import 的時候 ,
就不會遞歸運行了。

 3. 進程建立使用windows

from  multiprocessing import Process

def run():
    print("22222")
if __name__=="__main__":
    p=Process(target=run)      #  實例化進程
    p.start()


print("*******************************************")

# 進程傳參數
def run(*args):
    print(args)
if __name__=="__main__":
    p=Process(target=run,args=(10,20,30))      #  實例化進程
    p.start()

print("*******************************************")

# 來查看進程直間的關係   os.getpid() 查看當前進程號    os.getppid() 查看當前父進程號  
def run(*args):
    print(args)
    time.sleep(1)
    print(1111111111111111111111111111)
    print(os.getpid(),"查看當前子進程號3")       # 1748   # os.getpid() 查看當前進程號
    print(os.getppid(),"查看父進程號4")          # 10120   os.getppid() 查看當前父進程號

if __name__ == "__main__":
    p1 = Process(target=run, args=(10, 20, 30))  # 實例化進程
    p1.start()
    print("我是主進程。。。。。")
    print(os.getpid(),"查看當前主進程號1")          #10120      # os.getpid() 查看當前進程號
    print(os.getppid(),"查看當前執行父進程號2")     #  7372  #   os.getppid() 查看當前父進程號
    print(p1.name)                                 # Process-1

print("*******************************************")

# 多進程
"""multiprocessing 庫
是一個跨平臺版本多進程模塊 提供了一個Process類來表明一個進程對象
"""
from multiprocessing import Process
from time import sleep
import os
# 子進程須要執行代碼
def run(str):
    print("子進程啓動了")
    sleep(3)
    print("子進程結束")

if __name__ == "__main__":
    print("main是主(父)進程啓動....")
    # 01 建立進程 子進程
    p=Process(target=run,args =("nice",))  #    target 說明進程執行的指定代碼(函數)
    # 02  啓動進程
    # 父進程的結束不能影響子進程 讓父進程等待子進程結束在執行父進程
    p.start()
    print("父進程結束....")
    sleep(2)

# 執行順序
#     main是主(父)進程啓動....
#     父進程結束....
#     子進程啓動了
#     子進程結束



4. 多進程啓動(for循環 join進程感知)安全

def run(*args):
       print(args)
if __name__=="__main__":
    p1=Process(target=run,args=(10,20,30))      #  實例化進程
    p1.start()
    p2= Process(target=run, args=(555,666,777))
    p2.start()
    print("我是主進程")

print("***********************************************"def run(*args):
    print(args)
if __name__ == "__main__":
    for i in  range(5):
        p1 = Process(target=run, args=(10, 20, 30))  # 實例化進程
        p1.start()

print("***********************************************"
進程方法應用join 感知進程結束 至關於異步程序 改成同步程序 def run(*args): print(args) print("我是子進程2222222222222") time.sleep(2) print("我是子進程333333333333") if __name__ == "__main__": p1 = Process(target=run, args=(10, 20, 30)) # 實例化進程 p1.start() p1.join() # 應用join 感知進程結束 至關於異步程序 改成同步程序 有一個阻塞效果 就是子進程結束完了才執行主進程 print("我是主進程111111111111")
print("***********************************************"
join 進程方法應用感知 def run(): print("我是子進程2222222222222") time.sleep(2) # 在這休息兩秒 可是程序沒有停下 在休息2秒的過程當中 他在執行上面打印4次 就沒有等 在執行下面打印4次 print("我是子進程333333333333") if __name__ == "__main__": ret=[] for i in range(4): p1 = Process(target=run,) # 實例化進程 ret.append(p1) p1.start() for p in ret: p.join() #等待 上面因此進程必須執行完了才能執行下面代碼 在join以前是異步執行 當遇到join有個阻塞效果就變成同步執行 print("完成了哈哈哈.......") # 就至關於在join以前 開闢了四條跑道 這四個進程在各自的跑道跑 可是這四個進程有跑的慢的和跑的快的(意思就是每一個進程速度不同) # 當遇到join 跑的快的進程要等跑的慢的進程(意思就是四個進程都跑完) 在計算成績各自跑的成績 就變成了同步
print("***********************************************"
join(進程方法應用join 感知進程結束 至關於異步程序 改成同步程序)
def run(filename,coon): with open(filename,"w") as f1: f1.write(coon*10*'*') if __name__ == "__main__": ret=[] for i in range(4): p1 = Process(target=run,args=("info%s"%i,i)) # 實例化進程 ret.append(p1) p1.start() print(ret) for p in ret:p.join() # 等待上面寫完了在向用戶展現因此寫的文件 # 有個阻塞等待效果 join以前是異步寫入 遇到join變同步寫入完了 才能執行下面代碼 print([i for i in os.walk(r"H:\python之路2\day1")]) # # 同步0.1=400 =40 # 異步 400 0.1 =0.1
print("***********************************************"
通個類繼承來實現開啓多個進程
class MyProcess(Process): def __init__(self,a,b): super().__init__() # 繼承Proceess self.a=a self.b=b def run(self): print(self.a) print(self.b) print(self.pid) if __name__=="__main__": p1=MyProcess(1,2) p1.start() #至關於 # p2.run() 只是內部做爲處理的 p2 = MyProcess(555, 99999) p2.start() # 至關於 # p2.run() 只是內部做爲處理的 p1.join() p2.join() print("我是主進程!!!!!!!!!!!!!!1")




print("**********************************************************")


進程池概念 Pool
import os,time,random
from multiprocessing import Pool   # 多進程就用Pool  (進程池)


def run(name):

    print("子進程啓動22222",name,getpid())
    print("子進程程結束2222",name,getpid())

if __name__ == '__main__':

    print("父進程啓動11111")

    # 01 建立多個進程
    #     進程池
    #      表示能夠同時執行進程數量
    #      Pool默認大小是cpu核心數
    pp=Pool(2)
    for i in range(5):
        # 02 建立進程 放入進程池統一管理
        pp.apply_async(run,args=(i,))
        
#apply 阻塞       同步方法
# apply_async  阻塞     異步方法

# 注意:在調用join以前必須先調用close 調用close以後就不能再繼續添加新的進程了
pp.close()
#注意: 是進程池對象調用join會等待進程池中全部的子進程結束完畢再去執行父進程
pp.join()
print("父進程結束11111")
# 多進程
"""multiprocessing 庫

是一個跨平臺版本多進程模塊 提供了一個Process類來表明一個進程對象
"""
from multiprocessing import Pool   #  使用多進程
import os ,time ,random

def run(name):
     print("子進程啓動--%s"%(name,os.getpid()))
     # print(name,os.getpid())
     start=time.time()
     time.sleep(random.choiec([1,2,3]))
     end=time.time()
     print("子進程%d結束--%s--耗時%2.f"%(name,os.getpid(),end-start))
     # print(name,os.getpid(),end-start)
     # 
if __name__=="__main__":

  print("父進程啓動......................")

   # 01建立多進程
   #    進程池
   # Pool()  默認是大小cpu核心數   
  pp=Pool(2)     #表示能夠同時執行的進程數量

  for i in range(3):  # 建立3個進程
        # 建立進程,放入進程池統一管理
        pp.apply_async(run,args=(i,))

   # 在調用join以前必須先調用close調用close以後就不能再繼續添加新的進程了
  pp.close()
   # 進程池對象調用join 會等待進程池中全部的子進程結束完畢再去執行父進程
  pp.join()
  print("父進程結束......................")

 5. 進程之間數據隔離網絡

n=20
def run():
    global n
    n = 60
    print(n)  # 60
run()
print(n)   # 60


print("*********************************************")

num=100
# 說明子進程和父進程用的num是徹底不一樣的   是兩個徹底不一樣的變量
def run():
     print("子進程開始")
     global num            #global 表示使用全局變量
     num+=1
     print(num)
     print("子進程結束")

if __name__=="__main__":
     print("父進程開始")
     p=Process(target=run)
     p.start()
     p.join()
     print("父進程結束---",num)
# 在子進程中修改全局變量對父進程中的全局變量沒有影響
# 在建立子進程時對全局變量作了個備份  
# 在父進程和子進程中的num是兩個徹底不一樣的變量
# 執行順序
#     父進程開始
#     子進程開始
#     101
#     子進程結束
#     父進程結束--- 100


print("*********************************************")

def run():
    global n
    n=1000
    print("子進程",os.getpid(), n) # 子進程 8016 1000

if __name__ == "__main__":
    n = 600
    p1 = Process(target=run)  # 實例化進程
    p1.start()
    p1.join()       # 阻塞等待子進程結束後才執行主進程
    print("主進程",os.getpid(),n)    # 主進程 5244 600


print("*********************************************")

    def work():
    global n
    n=222
    print('子進程內: ',n)  # 子進程內:  222
if __name__ == '__main__':
    n = 100
    p=Process(target=work)
    p.start()
    print('主進程內: ',n)  # 主進程內:  100

 6. 進程實現網絡編程(注意子進程中不能加input)app

server 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 run(conn,addr):
    print(addr)
    while True:
        msg=conn.recv(1024)
        conn.send(msg.upper())

if __name__ == '__main__':
    while True:
        conn,addr=server.accept()
        p=Process(target=run,args=(conn,addr))
        p.start()

print"*******************************************"client from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
    msg=input('請輸入字母: ').strip()
    client.send(msg.encode('utf-8'))
    msg=client.recv(1024)
    print(msg.decode('utf-8'))

 7. 守護進程dom

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

主進程建立守護進程
  其一:守護進程會在主進程代碼執行結束後就終止
  其二:守護進程內沒法再開啓子進程,不然拋出異常
注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止。
import os
import time
from multiprocessing import Process
"""class Myprocess(Process):
    def __init__(self,person):
        super().__init__()
        self.person = person
    def run(self):
        print(os.getpid(),self.name)
        print('%s正在吃飯' %self.person)

if __name__=="__main__":
    p = Myprocess('張三')
    p.daemon = True  # 必定要在p.start()前設置,設置p爲守護進程,禁止p建立子進程,而且父進程代碼執行結束,p即終止運行
    p.start()
    time.sleep(2)  # 在sleep時查看進程id對應的進程ps -ef|grep id
    print('主進程')


print("******************************************************")



def run1():
    while True:
        time.sleep( 0.2)
        print("我還活起的!!!!!!!!")

if __name__=="__main__":
    p1=Process(target=run1)
    p1.daemon = True # 設置守護進程 (主進程代碼執行結束 子進程代碼也會天然而然結束 )
    p1.start()            # 隨着主進程代碼結束完畢 的結束  而結束
    print(p1.is_alive())   #  判斷進程是否或着
    i=0
    while i<5:
        print("我是主進程1111111111111111111")
        time.sleep(2)
        i+=1
    print(p1.is_alive())    #  判斷進程是否或着


print("******************************************************")

def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

p1=Process(target=foo)
p2=Process(target=bar)
if __name__=="__main__":
    p1.daemon=True
    p1.start()
    p2.start()
    time.sleep(0.1)
    print("main-------")
    # 打印該行則主進程代碼結束,則守護進程p1應該被終止.#可能會有p1任務
    # 執行的打印信息123,由於主進程打印main----時,p1也執行了,可是隨即被終止.
    # main - ------
    # 456
    # end45

 8. 進程方法is_alive()  and    terminate()異步

from multiprocessing import Process
import time
import random

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

    def run(self):
        print('%s正在和網紅臉聊天' %self.name)
        time.sleep(2)
        print('%s還在和網紅臉聊天' %self.name)

if __name__ == '__main__':

    p1=Myprocess('順悟空')
    p1.start()

    p1.terminate()#  結束一個子進程      關閉進程,不會當即關閉,因此is_alive馬上查看的結果可能仍是存活
    print(p1.is_alive()) #結果爲True     檢查進程狀態 是否活着

    print('開始')
    print(p1.is_alive()) #結果爲False

    print("我是主進程哈哈哈哈哈")

# p1.terminate()   在主進程中結束一個子進程 結束一個子進程不是執行了立馬生效 須要一個操做系統響應的過程
相關文章
相關標籤/搜索