進程

首先,先從多任務講起:
現代操作系統(Windows、Mac OS X、Linux、UNIX等)都支持"多任務"
什麼叫多任務???
操作系統同時可以運行多個任務

早期電腦都是單核cpu,他執行任務原理:
操作系統輪流讓各個任務交替執行,QQ執行2Us,切換到微信,執行2Us,
再切換到陌陌,執行2Us,……。表面上看,每個任務反覆執行下去,但是CPU調度
執行太快了,導致我們感覺就像所有任務都在同時執行一樣。

現在是多核CPU實現多任務原理:
真正的並行執行多任務只能在多核CPU上實現,但是由於任務數量遠遠多於CPU核心數量
所以,操作系統也會自動把很多任務輪流調度到每個核心上的執行

併發:看上去一起執行,任務數多於核心數
並行:真正一起執行,任務數小於等於CPU核心數

實現多任務的方式:
1、多進程模式
2、多線程模式(常用)
3、協程模式(在開發中,很少用)
4、多進程+多線程 模式
接下來講講進程:
任務管理器:裏面都是進程
對於操作系統而言,一個任務就是一個進程
進程是系統中程序執行和資源分配的基本單位,每個進程都有自己的數據段(存儲數據),
代碼段(存儲代碼)、和堆(存儲一些對象的)棧(普通的變量就在棧上)段。

進程的目的:實現多任務,提高我們的執行效率
     進程: 就是創建一個任務,讓它去執行其他的功能

===============================================================================

from time import sleep


def run():
    while True:
        print("sunck is a nice man")
        sleep(1.2)


if __name__ == '__main__':
    while True:
        print("sunck is a good man")
        sleep(1)


    # 不會執行 run 方法,只有上面的while循環結束纔可以執行
    # 要讓這個兩個任務同時執行,就是多任務
    run()

運行結果:
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man
sunck is a good man

===============================================================================

multiprocessing 庫
multiple: adj.數量多的;多種多樣的;
            n.倍數;
processing: v.處理;加工;
            n.過程;加工處理;處置;進行;
            adj.經過特殊加工的;(用化學方法等)處理過的;

在linux下可以使用C語言的方法fork實現多進程,但是它不支持window,
但是這個三方庫multiprocessing庫是一個跨平臺版本的多進程模塊
提供了一個Process類來代表一個進程對象

所以我們要使用多進程就要引入multiprocessing庫


import os
from multiprocessing import Process
from time import sleep


# 子進程需要執行的代碼
def run(adj):
    # os.getpid() 獲取當前進程ID號
    # os.getppid() 獲取當前進程的父進程ID號
    while True:
        print("sunck is a %s man--%s--%s"%(adj, os.getpid(),os.getppid()))
        sleep(1.2)


if __name__ == '__main__':
    print("主(父)進程啓動")
    # os.getpid() 獲取當前父進程ID號
    print(os.getpid())

    # 創建一個子進程(在父進程下創建一個進程,故稱爲該進程的子進程)
    p = Process(target=run, args=("nice",))
    # target:說明 該子進程要執行的任務、代碼、函數
    # args:可以給target的函數傳參數,是一個元組類型,單個參數要加逗號,

    # 啓動進程
    p.start()

    while True:
        print("sunck is a good man")
        sleep(1)
運行結果:
主(父)進程啓動
1975
sunck is a good man
sunck is a nice man--1976--1975
sunck is a good man
sunck is a nice man--1976--1975

===============================================================================

'''全局變量在多個進程中是不能共享的'''

from multiprocessing import Process
from time import sleep


NUM = 100


def run():
    print("子進程開始")
    global NUM
    NUM += 1
    print(NUM)
    print("子進程結束")

if __name__ == '__main__':
    print("父進程開始")
    
    
    p = Process(target=run)
    p.start()
    p.join()
    
    print(NUM)
    # 在子進程中修改全局變量對父進程中的全局變量沒有影響
    # 爲什麼沒影響呢?因爲他在創建子進程時,對全局變量做了一個備份,父進程中的與子進程中的
    # NUM是兩個完全不同的變量
    print("父進程結束--%d" % NUM)

運行結果:
父進程開始
子進程開始
101
子進程結束
100
父進程結束--100
# 父子進程的先後執行順序

from multiprocessing import Process
from time import sleep

def run(args):
    print("子進程啓動")
    sleep(3)
    print("子進程結束")

if __name__ == '__main__':
    print("主(父)進程啓動")

    p = Process(target=run, args=("nice",))
    p.start()

    # 父進程的結束不能影響子進程,讓父進程等待子進程,再執行父進程
    p.join()

    print("父進程結束")

 

'''
進程池
'''

import os
import time
import random

# 爲了對多個進程好管理,使用進程池
# from multiprocessing import Process
from multiprocessing import Pool


def run(name):
    print('子進程%s啓動--%s' % (name, os.getpid()))
    strat = time.time()
    time.sleep(random.choice([1, 2, 3]))
    end = time.time()
    print('子進程%s結束--%s--耗時%.2f' % (name, os.getpid(), end-strat))


if __name__ == '__main__':
    print('父進程啓動')

    # 創建多個進程
    # 進程池
    # 4:表示可以同時執行的進程數量
    # 參數可以寫,pool默認大小是CPU核心數
    pp = Pool(4)

    # 創建進程,創建的進程數要大於CPU核心數,這樣才能體驗到多進程的效果
    # 這裏因爲進程都是幹一樣的活,所以使用for循環創建進程
    # 子進程的執行數據是沒有順序的。
    for i in range(5):
        # 創建進程,放進進程池,統一管理
        pp.apply_async(run, args=(i,))

    '''
    如果每個進程乾的活不一樣,那就單獨創建每一個進程,不要寫for循環。
    例:
    pp.apply_async(func1, agrs=())
    pp.apply_async(func2, agrs=())
    pp.apply_async(func3, agrs=())
    pp.apply_async(func4, agrs=())
    pp.apply_async(func5, agrs=())
    '''

    # 在調用join之前,必須先調用close,並且在調用close之後,就不能再繼續添加新的進程了
    pp.close()
    # 進程池對象調用的join,會等待進程池中的所有的子進程結束完畢,再去執行父進程。
    pp.join()

    print("父進程結束")

'''
運行結果:  這裏進程看似0,1,2,3啓動的,實際上,進程啓動是沒有順序的。
父進程啓動
子進程0啓動--5251
子進程1啓動--5252
子進程2啓動--5253
子進程3啓動--5254
子進程2結束--5253--耗時1.00
子進程0結束--5251--耗時1.00
子進程4啓動--5253
子進程3結束--5254--耗時1.00
子進程1結束--5252--耗時2.00
子進程4結束--5253--耗時3.00
父進程結束
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 多進程實現文件拷貝

import os
import time

from multiprocessing import Pool


# 實現文件的拷貝
def copy_file(read_file_path, write_file_path):
    read_file = open(read_file_path, 'rb')
    write_file = open(write_file_path, 'wb')
    context = read_file.read()
    write_file.write(context)
    read_file.close()
    write_file.close()


path = r''
to_path = r''

if __name__ == '__main__':
    # 讀取path下的所有文件
    file_list = os.listdir(path)

    start = time.time()
    pp = Pool(2)
    for file_name in file_list:
        pp.apply_async(copy_file,
                       args=(os.path.join(path, file_name),
                             os.path.join(to_path, file_name)
                             )
                       )
        pp.close()
        pp.join()
        end = time.time()
        run_time = end - start
        print('總耗時---%d' % run_time)

 

#二次封裝的文件名,一般是:自己的名字+第三方庫的名稱

import os
import time
from multiprocessing import Process


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

    def run(self):
        super().run()
        print('子進程(%s-%s)啓動' % (self.name, os.getpid()))
        # 子進程的功能
        time.sleep(3)
        print('子進程(%s-%s)結束' % (self.name, os.getpid()))

==================================================================

from sunckProcess import SunckProcess


if __name__ == '__main__':
    print('父進程啓動')

    # 創建子進程
    p = SunckProcess('test')
    # 在這裏不要調用進程裏面的run方法,調用它的start就會自動調用進程對象的run方法
    p.start()
    p.join()

    print("父進程結束")

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章