proses
Berbilang benang dalam Python sebenarnya bukan berbilang benang sebenar Jika anda ingin menggunakan sepenuhnya sumber CPU berbilang teras, anda perlu menggunakan berbilang proses dalam kebanyakan kes dalam Python. Python menyediakan pakej berbilang pemprosesan yang sangat mudah digunakan Anda hanya perlu menentukan fungsi dan Python akan melakukan segala-galanya. Dengan bantuan pakej ini, penukaran daripada proses tunggal kepada pelaksanaan serentak boleh dicapai dengan mudah. Multiprocessing menyokong sub-proses, komunikasi dan perkongsian data, melaksanakan bentuk penyegerakan yang berbeza dan menyediakan komponen seperti Proses, Baris Gilir, Paip dan Kunci.
1. Proses Kelas
Kelas yang mencipta proses: Proses([kumpulan [, sasaran [, nama [, args [, kwargs]]]]])
sasaran mewakili objek panggilan
args mewakili objek panggilan Tuple parameter kedudukan
kwargs mewakili kamus objek panggilan
nama ialah alias
kumpulan pada dasarnya tidak digunakan
Mari kita lihat contoh mencipta fungsi dan menggunakannya sebagai pelbagai proses:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval, name): print(name + '【start】') time.sleep(interval) print(name + '【end】') if __name__ == "__main__": p1 = multiprocessing.Process(target=worker, args=(2, '两点水1')) p2 = multiprocessing.Process(target=worker, args=(3, '两点水2')) p3 = multiprocessing.Process(target=worker, args=(4, '两点水3')) p1.start() p2.start() p3.start() print("The number of CPU is:" + str(multiprocessing.cpu_count())) for p in multiprocessing.active_children(): print("child p.name:" + p.name + "\tp.id" + str(p.pid)) print("END!!!!!!!!!!!!!!!!!")
Hasil keluaran:
Hasil keluaran berbilang proses
2. Buat proses ke dalam kelas
Sudah tentu kita juga boleh mencipta proses ke dalam kelas, seperti dalam contoh di bawah, apabila proses p panggilan bermula() , kaedah run() dipanggil secara automatik.
# -*- coding: UTF-8 -*- import multiprocessing import time class ClockProcess(multiprocessing.Process): def __init__(self, interval): multiprocessing.Process.__init__(self) self.interval = interval def run(self): n = 5 while n > 0: print("当前时间: {0}".format(time.ctime())) time.sleep(self.interval) n -= 1 if __name__ == '__main__': p = ClockProcess(3) p.start()
Hasil keluaran adalah seperti berikut:
Buat kelas proses
3 Atribut Daemon
Jika anda ingin tahu untuk kegunaan atribut daemon, lihat dua contoh berikut, satu dengan atribut daemon ditambah dan satu tanpa, bandingkan hasil output:
Contoh tanpa menambah atribut deamon:
# -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.start() print('【EMD】')
Hasil output:
【EMD】 工作开始时间:Mon Oct 9 17:47:06 2017 工作结果时间:Mon Oct 9 17:47:09 2017
Dalam contoh di atas, proses p menambah atribut daemon:
# -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.daemon = True p.start() print('【EMD】')
Hasil output:
boleh dilihat mengikut hasil output, jika dalam proses anak Atribut daemon ditambahkan ke , jadi apabila proses utama tamat, proses anak juga akan berakhir. Jadi tiada maklumat tentang proses kanak-kanak dicetak. . Kemudian kita boleh menggunakan kaedah gabungan Fungsi utama kaedah gabungan adalah untuk menyekat proses semasa sehingga proses yang memanggil kaedah gabungan selesai melaksanakan, dan kemudian terus melaksanakan proses semasa.Jadi lihat contoh menambah kaedah gabungan:
【EMD】Hasil output:
import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.daemon = True p.start() p.join() print('【EMD】')
5, Pool
Jika banyak proses anak diperlukan, adakah kita perlu menciptanya satu persatu?
Sudah tentu tidak, kita boleh menggunakan kaedah kumpulan proses untuk mencipta proses anak dalam kelompok.
Contohnya adalah seperti berikut:
工作开始时间:Tue Oct 10 11:30:08 2017 工作结果时间:Tue Oct 10 11:30:11 2017 【EMD】
Hasil output adalah seperti berikut:
# -*- coding: UTF-8 -*- from multiprocessing import Pool import os, time, random def long_time_task(name): print('进程的名称:{0} ;进程的PID: {1} '.format(name, os.getpid())) start = time.time() time.sleep(random.random() * 3) end = time.time() print('进程 {0} 运行了 {1} 秒'.format(name, (end - start))) if __name__ == '__main__': print('主进程的 PID:{0}'.format(os.getpid())) p = Pool(4) for i in range(6): p.apply_async(long_time_task, args=(i,)) p.close() # 等待所有子进程结束后在关闭主进程 p.join() print('【End】')
Terdapat satu perkara yang perlu diperhatikan di sini: memanggil kaedah join() objek Pool akan menunggu semua proses kanak-kanak menyelesaikan pelaksanaan, dan close() mesti dipanggil sebelum memanggil join().
主进程的 PID:7256 进程的名称:0 ;进程的PID: 1492 进程的名称:1 ;进程的PID: 12232 进程的名称:2 ;进程的PID: 4332 进程的名称:3 ;进程的PID: 11604 进程 2 运行了 0.6500370502471924 秒 进程的名称:4 ;进程的PID: 4332 进程 1 运行了 1.0830621719360352 秒 进程的名称:5 ;进程的PID: 12232 进程 5 运行了 0.029001712799072266 秒 进程 4 运行了 0.9720554351806641 秒 进程 0 运行了 2.3181326389312744 秒 进程 3 运行了 2.5331451892852783 秒 【End】, anda boleh menjalankan 5 proses pada masa yang sama.
6. Komunikasi antara proses
Proses pastinya perlu berkomunikasi. Modul pemproses berbilang Python membungkus mekanisme asas dan menyediakan pelbagai kaedah seperti Baris Gilir dan Paip untuk bertukar data.
Ambil Queue sebagai contoh, buat dua proses anak dalam proses induk, satu menulis data ke Queue, dan satu lagi membaca data dari Queue:
p = Pool(5)
Hasil output ialah:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- from multiprocessing import Process, Queue import os, time, random def write(q): # 写数据进程 print('写进程的PID:{0}'.format(os.getpid())) for value in ['两点水', '三点水', '四点水']: print('写进 Queue 的值为:{0}'.format(value)) q.put(value) time.sleep(random.random()) def read(q): # 读取数据进程 print('读进程的PID:{0}'.format(os.getpid())) while True: value = q.get(True) print('从 Queue 读取的值为:{0}'.format(value)) if __name__ == '__main__': # 父进程创建 Queue,并传给各个子进程 q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 启动子进程 pw pw.start() # 启动子进程pr pr.start() # 等待pw结束: pw.join() # pr 进程里是死循环,无法等待其结束,只能强行终止 pr.terminate()