1. 程式人生 > 其它 >Python3 多程序

Python3 多程序

什麼是程序?

  • 程式:一個未執行的二進位制檔案,叫做程式。如Windows下的PE檔案

  • 程序:二進位制檔案執行後,檔案本身以及用到的資源稱為程序,他是作業系統分配資源的基本單元。

  • 多工:不止可以通過執行緒完成多工,還可以通過程序完成多工。

使用Process實現多程序

from multiprocessing import Process
import time

def test(test):
    time.sleep(5)
    print("這是{}".format(test))

def main():
    p1 = Process(target=test,kwargs={"test":"t1"})
    p2 = Process(target=test,kwargs={"test":"t2"})
    p1.start()
    p2.start()

if __name__ == "__main__":
    main()

通過佇列完成程序間通訊

from multiprocessing import Queue,Process
import time
import os

def queue_put(q):
    for i in range(10):
        q.put(i)
        print("PID:{} ,{} 已存入佇列,當前佇列共{}個元素".format(os.getpid(),i,q.qsize()))
        time.sleep(5)

def queue_get(q):
    for i in range(10):
        print("PID:{} ,{} 已取出佇列,當前佇列共{}個元素".format(os.getpid(),q.get(),q.qsize()))
        time.sleep(5)

def main():
    q = Queue(5)#建立一個佇列,佇列可以儲存5個數據
    # q.put("a")#向佇列中新增資料,如果佇列存滿,程式會阻塞等待
    # q.get()#從佇列中獲取資料,如果佇列為空,程式會阻塞等待
    # #q.put_nowait()如果佇列存滿,程式會報異常
    # #q.get_nowait()如果佇列為空,程式會報異常
    # q.qsize()#取出佇列中資料個數
    # q.empty()#判斷佇列是否為空
    # q.full()#判斷佇列是否存滿
    p1 = Process(target=queue_put,args=(q,))
    p2 = Process(target=queue_get,args=(q,))
    p1.start()
    p2.start()

if __name__ == "__main__":
    main()

程序池

import hashlib
from multiprocessing import Pool

def js_hash(s):
    md5 = hashlib.md5()
    md5.update(s.encode('utf-8'))
    md5 = md5.hexdigest()
    if '0e' == md5[0:2] and md5[2:].isdecimal():
        print(s,md5)
if __name__ == '__main__':
    p = Pool(5)#建立一個程序池,最大程序數5,如果不填,則無限制
    for i in range(0,99999999999999):
        s = '0e' + str(i)
        p.apply_async(js_hash, args=(s,))#apply_async(要呼叫的目標,args=(傳遞的引數,))
    p.close()#關閉程序池,關閉後進程池不再接受新的請求
    p.join()#等待所有子程序執行完畢,必須放在close語句後

案例:多工檔案copy

import os,sys
from multiprocessing import Pool,Manager

def copy_file(q,file_name,old_dir,new_dir):
    #print("將 {} 檔案複製到 {} 目錄下".format(file_name,new_dir))
    if os.path.isdir(old_dir + "\\" + file_name):
        # print(file_name,"是個目錄")
        q.put(file_name)
    else:
        #print(file_name,"是個檔案")
        with open(old_dir + "\\" + file_name,'rb') as file:
            with open(new_dir + "\\" + file_name,"wb") as file_new:
                file_new.write(file.read())

def main():
    # 1、獲取要拷貝的檔名
    print("注意!此程式不完善,尚不能copy資料夾中資料夾的檔案")
    old_dir = input(r"輸入需要copy的原始檔夾路徑,如(C:\null):")
    # 2、建立新資料夾
    new_dir = input(r"輸入需要copy的目標資料夾路徑,如(C:\null_副件):")
    try:
        os.mkdir(new_dir)
    except:
        pass
    # 3、獲取所有需要copy檔名
    files_name = os.listdir(old_dir)
    # 4、建立程序池
    po = Pool(5)
    # 程序池使用佇列需要使用Manager類下的Queue
    q = Manager().Queue()
    # 5、向程序池新增複製檔案的任務
    for file_name in files_name:
        po.apply_async(copy_file,args=(q,file_name,old_dir,new_dir))
    po.close()
    #po.join()
    copy_ok = 0
    copy_num = len(files_name)
    folders = []
    while True:
        copy_ok += 1
        sys.stdout.write("\r拷貝進度:{:.2f}%".format(copy_ok*100/copy_num))
        try:
            folders.append(q.get_nowait())
        except:
            pass
        #將未拷貝的資料夾存入列表
        if copy_ok >= copy_num:
            break
    print("\n以下資料夾未複製:",",".join(folders))
    
if __name__ == "__main__":
    main()

參考:
multiprocessing --- 基於程序的並行 — Python 3.9.5 文件