日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

112 Python程序中的進程操作-開啟多進

系統 1740 0

目錄

  • 一、multiprocess模塊
  • 二、multiprocess.process模塊
  • 三、Process類
    • 3.1 方法介紹
    • 3.2 屬性介紹
    • 3.3 在windows中使用Process類的注意事項
  • 四、process類的使用
    • 4.1 創建并開啟子進程的兩種方式
    • 4.2 join方法
    • 4.3 查看主進程和子進程的進程號
    • 4.4 查看進程名和進程狀態、設置進程名
    • 4.5 terminate結束子進程
    • 4.6 Process中的守護進程
  • 五、socket聊天并發實例
    • 5.1 使用多進程實現socket聊天并發-server端
    • 5.2 使用多進程實現socket聊天并發-client端

運行中的程序就是一個進程。 所有的進程都是通過它的父進程來創建的 。因此,運行起來的python程序也是一個進程,那么我們也可以在程序中再創建進程。多個進程可以實現并發效果,當我們的程序中存在多個進程的時候,在某些時候,就會讓程序的執行速度變快。

在linux c語言中創建線程使用的fork函數,而Python就需要借助響應的模塊

一、multiprocess模塊

仔細說來,multiprocess不是一個模塊而是python中一個操作、管理進程的包。 之所以叫multi是取自multiple的多功能的意思,在這個包中幾乎包含了和進程有關的所有子模塊。由于提供的子模塊非常多,為了方便大家歸類記憶,我將這部分大致分為四個部分:創建進程部分,進程同步部分,進程池部分,進程之間數據共享。

二、multiprocess.process模塊

process模塊是一個創建進程的模塊,借助這個模塊,就可以完成進程的創建。

三、Process類

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為子進程的名稱

3.1 方法介紹

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

3.2 屬性介紹

  • 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字符的字符串。這個鍵的用途是為涉及網絡連接的底層進程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)

3.3 在windows中使用Process類的注意事項

在Windows操作系統中由于沒有fork(linux操作系統中創建進程的機制),在創建子進程的時候會自動 import 啟動它的這個文件,而在 import 的時候又執行了整個文件。因此如果將process()直接寫在文件中就會無限遞歸創建子進程報錯。所以必須把創建子進程的部分使用 if __name__ =='__main__' 判斷保護起來,import 的時候,就不會遞歸運行了。

四、process類的使用

在一個python進程中開啟子進程,start方法和并發效果。

4.1 創建并開啟子進程的兩種方式

  • 方式一:通過函數

                  
                    from multiprocessing import Process
    import time
    
    '''
    開啟子進程的兩種方式:
    1. 通過函數
    2. 通過類。繼承Process
    '''
    
    def task(name):
        print("進程{%s} start"%(name))
        time.sleep(2)
        print(f"進程{name} end")
    
    # 必須加main
    if __name__ == '__main__':
        ######## 方式1(通過函數)
        p = Process(target=task,args=("xc",))   # args用于傳參,是個元祖,必須加逗號
        p.start() # 告訴操作系統啟動子進程,但一定是父進程先執行,多個子進程的執行順序是根據操作系統調度決定的
        print('主進程/父進程')
        print('主進程/父進程')
        p1 = Process(target=task,args=("cyx",))
        p1.start()  # 告訴操作系統啟動子進程,但一定是父進程先執行,多個子進程的執行順序是根據操作系統調度決定的
        print('主進程/父進程')
        print('主進程/父進程')
        print('主進程/父進程')
        print('主進程/父進程')
                  
                
  • 方式二:通過類。繼承Process

                  
                    from multiprocessing import Process
    import time
    
    '''
    開啟子進程的兩種方式:
    1. 通過函數
    2. 通過類。繼承Process
    '''
    
    class myProcess(Process):
        def __init__(self,name):
            # self.name = name #錯誤 ### 這樣沒有給對象添加屬性name,而是在修改父類的進程名(name)
    
            # 父類Process的進程名也是name
            super().__init__()  # 調用父類super().init方法完成創建進程初始化,重新給name屬性賦值了。
            self.name = name    ## 在父類的init方法后設置name,才是為自己對象添加屬性
    
            # super().__init__(name=name)  # 調用父類super().init,并設置進程名(name)
    
    
        def run(self):  # 創建進程會默認調用run方法
            print("進程%s start" % (self.name))
            time.sleep(2)
            print(f"進程{self.name} end")
    
    # 必須加main
    if __name__ == '__main__':
        p = myProcess("xc")
        p.start()
        print('主進程/父進程')
        print('主進程/父進程')
        p1 = myProcess("cyx")
        p1.start()  # 告訴操作系統啟動子進程,但一定是父進程先執行,多個子進程的執行順序是根據操作系統調度決定的
        print('主進程/父進程')
        print('主進程/父進程')
        print('主進程/父進程')
        print('主進程/父進程')
                  
                

4.2 join方法

join方法用于回收子進程

          
            from multiprocessing import Process
import time
  
def foo(x):
      print('進程  start ')
      time.sleep(x)
      print('進程  end ')
      
if __name__ == '__main__':
      ### 串行執行和回收子進程
      # p = Process(target=foo, args=(1,))
      # p2 = Process(target=foo, args=(2,))
      # p3 = Process(target=foo, args=(3,))
      # p.start() #
      # p.join() # 阻塞住主進程再等待子進程結束,然后再往下執行,(了解的是:內部會待用wait())
      # p2.start()
      # p2.join()
      # p3.start()
      # p3.join()
      # print('主')
  
      # 并發執行進程,并依次回收
      p = Process(target=foo, args=(1,))
      p2 = Process(target=foo, args=(2,))
      p3 = Process(target=foo, args=(3,))
      # 開啟進程
      p.start()
      p2.start()
      p3.start()
  
      # 回收進程
      p.join() # 阻塞住主進程再等待子進程結束,然后再往下執行,(了解的是:內部會待用wait())
      p2.join()
      p3.join()
      print('主')
          
        

4.3 查看主進程和子進程的進程號

          
            from multiprocessing import Process,current_process
import time
import os
  
  '''
  查看主進程和子進程的進程號
  1. 通過os.getpid()方法
  2. 通過multiprocessing模塊中的current_process().pid
  '''
  
  def task(name,x):
      print("當前進程pid:", current_process().pid)
      print(f"{name} start")
      time.sleep(x)
      print(f"{name} end")
  
  if __name__ == '__main__':
      p = Process(target=task,args=("進程1",1))
      p.start()
      # 方式一
      print("子進程pid:",p.pid)
      # 方式二
      # print("當前進程pid:",current_process().pid)
      print("當前進程pid",os.getpid())
      print("主進程的父進程pid",os.getppid())    # 實際上是pycharm的進程號
      print()
          
        

4.4 查看進程名和進程狀態、設置進程名

          
            '''
process設置名字: name屬性
process判斷進程是否存在:is_alive
'''

from multiprocessing import Process
import time
  
  def task(x):
      print("進程 start")
      time.sleep(x)
      print("進程 end")
  
  if __name__ == '__main__':
      p = Process(target=task,args=(1,))
      p.start()
      p.name = "進程1"
      print(p.name)
  
      print("子進程是否存在:", p.is_alive()) # True
      time.sleep(2)   # 延時2秒等待子進程結束
      print("子進程是否存在:", p.is_alive()) # False
  
      print("主進程")
          
        

4.5 terminate結束子進程

          
            '''
terminate()
告訴子進程讓他結束
'''

from multiprocessing import Process
import time
def task(x):
    print("進程 start")
    time.sleep(x)
    print("進程 end")

if __name__ == '__main__':
    p = Process(target=task,args=(10,))
    p.start()
    p.terminate()   # 告訴子進程讓他提前結束

    p.name = "進程1"
    print(p.name)

    print("子進程是否存在:", p.is_alive()) # True
    p.join()
    print("子進程是否存在:", p.is_alive()) # False

    print("主進程")
          
        

4.6 Process中的守護進程

首先,博主自己測試,實驗。Process中守護進程的部分和真正的守護進程概念并不一樣,因此只需要知道Process的守護進程即可。

          
            '''
daemon = True 把子進程變為守護進程
主進程的代碼執行完畢守護進程直接結束。但如果子進程代碼結束也會結束
'''
from multiprocessing import Process
import time
def task(x):
    print("進程 start")
    time.sleep(x)
    print("進程 end")


if __name__ == '__main__':
    p = Process(target=task,args=(2,))
    p.daemon = True  # 把子進程變為守護進程
    p.start()
    # print(p.pid)

    p.name = "進程1"
    print(p.name)
    print("子進程pid:", p.pid) #

    print("子進程是否存在:", p.is_alive()) # True
    time.sleep(3)
    print("子進程是否存在:", p.is_alive()) # False

    print("主進程")
    print("子進程是否存在:", p.is_alive())  # False

    time.sleep(200)
          
        

五、socket聊天并發實例

5.1 使用多進程實現socket聊天并發-server端

          
            import socket
from multiprocessing import Process

def talk(conn,client_addr):
    while 1:
            msg = conn.recv(1024)
            if not msg:
                break
            print(msg.decode("utf8"))
            conn.send(msg.upper())
            print(111)

if __name__ == '__main__':
    # 必須要寫在里面,不然會因為創建子線程重復調用導致端口被占用
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(("127.0.0.1", 8087))
    server.listen(5)

    while 1:
        print("等待連接")
        conn,addr = server.accept()
        print(addr,"連接成功")
        p = Process(target=talk,args=(conn,addr))
        p.start()
          
        

5.2 使用多進程實現socket聊天并發-client端

          
            import socket

if __name__ == '__main__':
    client = socket.socket()
    client.connect(("127.0.0.1",8087))
    while 1:
        msg = input("請輸入內容")
        client.send(msg.encode("utf8"))
        msg = client.recv(1024).decode("utf8")
        print(msg)
          
        

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 寻甸| 简阳市| 额济纳旗| 永川市| 枝江市| 文昌市| 郑州市| 大理市| 宁明县| 丰城市| 合山市| 洞口县| 万宁市| 黄梅县| 攀枝花市| 华安县| 岳普湖县| 南华县| 通城县| 水城县| 县级市| 万荣县| 汉中市| 岳阳县| 德昌县| 南皮县| 景洪市| 屏山县| 浙江省| 雅江县| 白朗县| 丁青县| 新沂市| 福泉市| 酒泉市| 介休市| 浦北县| 扬中市| 丘北县| 澄迈县| 九江市|