首頁 > 軟體

Python語法學習之程序的建立與常用方法詳解

2022-04-08 13:01:20

該章節我們來學習一下在 Python 中去建立並使用多程序的方法,通過學習該章節,我們將可以通過建立多個程序來幫助我們提高指令碼執行的效率。可以認為縮短指令碼執行的時間,就是提高執行我們指令碼的效率。接下來讓我們都看一下今天的章節知識點都有哪些?

程序的建立模組 - multiprocessing

建立程序函數 - Process

函數名介紹引數返回值
Process建立一個程序target, args程序物件

Process功能介紹:範例化一個物件;它需要傳入兩個引數 target 與 args:target 是一個函數,args 是對應一個函數的引數(args引數是一個元組)。其實我們可以這樣去理解,在一個指令碼中建立子程序,目的是為了讓它執行我們指令碼中的某個函數。換句話講,我們將指令碼中的某一個函數單獨的啟用一個程序去執行。

我們說過程序之間互不干擾,可以同時執行。所以我們可以認為主程序中的程式和子程序的函數是相互不干擾的,聽起來可能很難理解,一會兒下文我們進行一個案例的小練習,一遍幫助大家去更好的理解其中的含義。

程序的常用方法

函數名介紹引數返回值
start執行程序
join阻塞程序
kill殺死程序
is_alive判斷程序是否存活bool
  • start 函數:通過呼叫它,可以直接啟動我們建立的程序。它會馬上執行我們程序中傳入的函數,start 函數沒有任何引數,也沒有返回值。
  • join 函數:我們說過,主程序和子程序的程式會同時執行,互不影響。這樣就會有一個問題,有可能是 子程序 先執行完它的業務,也有可能是 主程序 先執行完它的業務邏輯。如果有的時候我們必須要先執行完 子程序的業務 再執行 主程序的業務 。則通過呼叫 join 函數,在這一函數下面執行的主程序業務要等待子程序完成之後才會繼續執行。我們將 join 這樣的函數叫做 等待/阻塞函數。join 函數沒有任何引數,也沒有返回值。
  • kill 函數:如果我們在執行子程序的過程中發現不需要這個子程序繼續執行了,就可以使用 kill 函數殺死當前的這個子程序,殺死的這個子程序不會在執行子程序中函數的業務邏輯。kill 函數沒有任何引數,也沒有返回值。
  • is_alive 函數:通過呼叫這個函數可以判斷當前的程序是否是存活狀態,它返回一個 bool 值。True 表示當前程序還在,程式還在繼續執行;如果是 False 則代表當前程序已經結束了

start 函數

演示案例:

  • 我們先定義兩個簡單的函數,每個函數定義兩個簡單的 for 迴圈。
  • 每執行一次迴圈,休眠一秒的時間。
  • 在兩次迴圈的開始定義一個範例化時間物件,用以計算兩次迴圈的時間間隔。
  • 同時,獲取指令碼執行的程序號; 看看是一個怎樣的結果。
# coding:utf-8


import time
import os


def work_for_first():

    for i in range(5):
        print(''work_for_first' 函數的迴圈值:%s', '程序號為:%s' % i, os.getpid())	# os.getpid() 為獲取程序號函數
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print(''work_for_second' 函數的迴圈值:%s',  '程序號為:%s' % i, os.getpid())
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 獲取執行 迴圈 之前的時間戳
    work_for_first()
    work_for_second()
    end_time = time.time() - start_time     # 獲取執行 迴圈 結束的時間戳
    print('耗時時間為:{}, 程序號為:{}'.format(end_time, os.getpid()))  # 獲取耗時與程序號

執行結果如下圖:

OKK!接下來進入我們今天要學習的主題。

將 work_for_first() 函數建立一個新的子程序去執行。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print(''work_for_first' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print(''work_for_second' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 獲取執行 迴圈 之前的時間戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因為我們傳入的函數沒有引數所以 args 可以不寫
    work_for_first_process.start()
    work_for_second()
    end_time = time.time() - start_time     # 獲取執行 迴圈 結束的時間戳
    print('耗時時間為:{}, 程序號為:{}'.format(end_time, os.getpid()))  # 獲取耗時與程序號

執行結果如下圖:

因為我們針對 work_for_first() 函數建立一個新的子程序去執行,所以我們的耗時變為了 5秒。那麼如果我們將 work_for_second() 函數也建立一個新的子程序去執行,耗時又會是多少呢?我們接著往下看。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print(''work_for_first' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print(''work_for_second' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 獲取執行 迴圈 之前的時間戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因為我們傳入的函數沒有引數所以 args 可以不寫
    work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    work_for_second_process.start()
    end_time = time.time() - start_time     # 獲取執行 迴圈 結束的時間戳
    print('耗時時間為:{}, 程序號為:{}'.format(end_time, os.getpid()))  # 獲取耗時與程序號

執行結果如下圖:

PS:從指令碼中執行入口的 main 函數可以看出 work_for_first() 函數 與 work_for_second() 函數 分別都由各自的子程序來執行,主程序實際執行的 只有 23行、29行、30行程式碼,所以從耗時來看,主程序實際上只執行了 0.026 秒。

這裡再思考一個問題,如果是每一個子程序都單獨的通過 .start 去啟動,那麼在子程序很多的情況下,啟動的確實會有一些慢了。這個時候我們就可以通過 for 迴圈的方式去啟動子程序。方式如下:

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()

join 函數

同樣的也會存在著這樣一種情況,我們希望子程序執行結束之後再去執行我們的主程序,這時候我們就會使用到 join 函數 。

這裡我們就利用上文的 程序 for迴圈同時啟動兩個子程序,然後我們再在下一個 for迴圈 執行 join 函數,我們看看會發生什麼。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print(''work_for_first' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print(''work_for_second' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 獲取執行 迴圈 之前的時間戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因為我們傳入的函數沒有引數所以 args 可以不寫
    # work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    # work_for_second_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.join()

    end_time = time.time() - start_time     # 獲取執行 迴圈 結束的時間戳
    print('耗時時間為:{}, 程序號為:{}'.format(end_time, os.getpid()))  # 獲取耗時與程序號

執行結果如下圖:

kill 函數 與 is_alive 函數

接下來我們再嘗試一個場景,利用 for 迴圈,我們同時啟動 work_for_first() 函數 與 work_for_second() 函數 的子程序。然後我們再在另一個 for 迴圈中,將 work_for_second() 函數 的子程序 kill 掉,然後判斷兩個子程序的存活狀態。

範例指令碼如下:

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print(''work_for_first' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print(''work_for_second' 函數的迴圈值:{},程序號為:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 獲取執行 迴圈 之前的時間戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因為我們傳入的函數沒有引數所以 args 可以不寫
    # work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    # work_for_second_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()
        time.sleep(1)   # 休眠一秒是為了 work_for_second_process 子程序 至少能夠執行一次


    for sun_process in (work_for_first_process, work_for_second_process):
        work_for_second_process.kill()
        if work_for_first_process.is_alive():
            print(''work_for_first_process' 子程序當前存活狀態為:True')
        elif not work_for_second_process.is_alive():
            print(''work_for_second_process' 子程序當前存活狀態為:False')

        sun_process.join()

    end_time = time.time() - start_time     # 獲取執行 迴圈 結束的時間戳
    print('耗時時間為:{}, 程序號為:{}'.format(end_time, os.getpid()))  # 獲取耗時與程序號

執行結果如下:

程序的相關問題

通過學習多程序的建立、啟動,我們可以充分的體會到程序給我們帶來的好處。它可以使我們的指令碼程式執行時間進行縮短,從而提高工作效率。

然而多程序也有一些問題:

  • 通過程序模組執行的函數無法獲取返回值,即便這個函數擁有 return 關鍵字也無法獲取到,這也是我們程序的弊端。
  • 多個程序同時修改檔案可能會出現錯誤。
  • 程序數量太多可能會造成資源不足、甚至宕機等情況。

關於程序的這些問題,其實也並不是不能解決。在後續更新的 程序間的通訊 、程序池與程序鎖 的章節我們再進行詳細的介紹。

到此這篇關於Python語法學習之程序的建立與常用方法詳解的文章就介紹到這了,更多相關Python 程序建立內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com