Python多進(jìn)程編程技術(shù)實(shí)例分析
本文以實(shí)例形式分析了Python多進(jìn)程編程技術(shù),有助于進(jìn)一步Python程序設(shè)計(jì)技巧。分享給大家供大家參考。具體分析如下:
一般來說,由于Python的線程有些限制,例如多線程不能充分利用多核CPU等問題,因此在Python中我們更傾向使用多進(jìn)程。但在做不阻塞的異步UI等場(chǎng)景,我們也會(huì)使用多線程。本篇文章主要探討Python多進(jìn)程的問題。
Python在2.6引入了多進(jìn)程的機(jī)制,并提供了豐富的組件及api以方便編寫并發(fā)應(yīng)用。multiprocessing包的組件Process, Queue, Pipe, Lock等組件提供了與多線程類似的功能。使用這些組件,可以方便地編寫多進(jìn)程并發(fā)程序。
Process
Process的使用有點(diǎn)像java.lang.Thread,但Thread是線程。start方法用以啟動(dòng)某個(gè)進(jìn)程。一個(gè)簡(jiǎn)單的示例:
from multiprocessing import Process
import os
import time
def sleeper(name, seconds):
print "Process ID# %s" % (os.getpid())
print "Parent Process ID# %s" % (os.getppid())
print "%s will sleep for %s seconds" % (name, seconds)
time.sleep(seconds)
if __name__ == "__main__":
child_proc = Process(target=sleeper, args=('bob', 5))
child_proc.start()
print "in parent process after child process start"
print "parent process abount to join child process"
child_proc.join()
print "in parent process after child process join"
print "the parent's parent process: %s" % (os.getppid())
實(shí)例化一個(gè)Process必須要指定target和args。target是新的進(jìn)程的入口方法,可以認(rèn)為是main方法。args是該方法的參數(shù)列表。啟動(dòng)進(jìn)程類似于啟動(dòng)Thread,必須要調(diào)用start方法。也可以繼承Process,覆蓋run方法,在run方法中實(shí)現(xiàn)該進(jìn)程的邏輯。調(diào)用join方法會(huì)阻塞當(dāng)前調(diào)用進(jìn)程,直到被調(diào)用進(jìn)程運(yùn)行結(jié)束。
手工終止一個(gè)進(jìn)程可以調(diào)用terminate方法,在UNIX系統(tǒng)中,該方法會(huì)發(fā)送SIGTERM信號(hào)量,而在windows系統(tǒng)中,會(huì)借助TerminateProcess方法。需要注意的是,exit處理邏輯并不會(huì)被執(zhí)行,該進(jìn)程的子進(jìn)程不會(huì)被終止,他們只會(huì)變成孤兒進(jìn)程。
Queue
Queue是多進(jìn)程安全的隊(duì)列,可以使用Queue實(shí)現(xiàn)多進(jìn)程之間的數(shù)據(jù)傳遞。put方法用以插入數(shù)據(jù)到隊(duì)列中,put方法還有兩個(gè)可選參數(shù):blocked和timeout。如果blocked為True(默認(rèn)值),并且timeout為正值,該方法會(huì)阻塞timeout指定的時(shí)間,直到該隊(duì)列有剩余的空間。如果超時(shí),會(huì)拋出Queue.Full異常。如果blocked為False,但該Queue已滿,會(huì)立即拋出Queue.Full異常。
get方法可以從隊(duì)列讀取并且刪除一個(gè)元素。同樣,get方法有兩個(gè)可選參數(shù):blocked和timeout。如果blocked為True(默認(rèn)值),并且timeout為正值,那么在等待時(shí)間內(nèi)沒有取到任何元素,會(huì)拋出Queue.Empty異常。如果blocked為False,有兩種情況存在,如果Queue有一個(gè)值可用,則立即返回該值,否則,如果隊(duì)列為空,則立即拋出Queue.Empty異常。Queue的一段示例代碼:
from multiprocessing import Process, Queue
def offer(queue):
queue.put("Hello World")
def test(queue, num):
queue.put("Hello World: " + str(num))
if __name__ == '__main__':
q = Queue()
p1 = Process(target=test, args=(q, 1))
p1.start()
p = Process(target=offer, args=(q,))
p.start()
p2 = Process(target=test, args=(q, 2))
p2.start()
p2 = Process(target=test, args=(q, 3))
p2.start()
print q.get()
print q.get()
print q.get()
print q.get()
print q.close()
輸出:
Hello World: 1
Hello World
Hello World: 2
None
Pipes
Pipe方法返回(conn1, conn2)代表一個(gè)管道的兩個(gè)端。Pipe方法有duplex參數(shù),如果duplex參數(shù)為True(默認(rèn)值),那么這個(gè)管道是全雙工模式,也就是說conn1和conn2均可收發(fā)。duplex為False,conn1只負(fù)責(zé)接受消息,conn2只負(fù)責(zé)發(fā)送消息。
send和recv方法分別是發(fā)送和接受消息的方法。例如,在全雙工模式下,可以調(diào)用conn1.send發(fā)送消息,conn1.recv接收消息。如果沒有消息可接收,recv方法會(huì)一直阻塞。如果管道已經(jīng)被關(guān)閉,那么recv方法會(huì)拋出EOFError。
from multiprocessing import Process, Pipe
def send(conn):
conn.send("Hello World")
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=send, args=(child_conn,))
p.start()
print parent_conn.recv()
同步
multiprocessing包提供了Condition, Event, Lock, RLock, Semaphore等組件可用于同步。下面是使用Lock的一個(gè)示例:
from multiprocessing import Process, Lock def l(lock, num): lock.acquire() print "Hello Num: %s" % (num) lock.release() if __name__ == '__main__': lock = Lock() for num in range(20): Process(target=l, args=(lock, num)).start()
總結(jié)
以上是Python multiprocessing庫(kù)的簡(jiǎn)單介紹和實(shí)例,熟悉Java多線程開發(fā)的同學(xué)是不是覺得很熟悉,和java的Concurrency API很像,不過javaConcurrency是處理多線程的而已,我們可以直接按照以前Java多線程的經(jīng)驗(yàn)用這些API。
感興趣的朋友可以測(cè)試運(yùn)行本文實(shí)例以加深理解。相信本文所述對(duì)大家Python程序設(shè)計(jì)的學(xué)習(xí)有一定的借鑒價(jià)值。
- python 多進(jìn)程通信模塊的簡(jiǎn)單實(shí)現(xiàn)
- Python多進(jìn)程同步Lock、Semaphore、Event實(shí)例
- Python多進(jìn)程通信Queue、Pipe、Value、Array實(shí)例
- python多進(jìn)程操作實(shí)例
- 淺析Python中的多進(jìn)程與多線程的使用
- 簡(jiǎn)單介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理
- python協(xié)程用法實(shí)例分析
- Python多線程、異步+多進(jìn)程爬蟲實(shí)現(xiàn)代碼
- 簡(jiǎn)述Python中的進(jìn)程、線程、協(xié)程
- 深入淺析python中的多進(jìn)程、多線程、協(xié)程
相關(guān)文章
Python設(shè)計(jì)足球聯(lián)賽賽程表程序的思路與簡(jiǎn)單實(shí)現(xiàn)示例
足球聯(lián)賽的賽制就是一支隊(duì)伍在一個(gè)賽季中主客場(chǎng)分別面對(duì)聯(lián)賽中除了自身以外的球隊(duì)一次,對(duì)此我們可以使用一種循環(huán)算法來實(shí)現(xiàn),接下來就一起來看一下Python設(shè)計(jì)足球聯(lián)賽賽程表程序的思路與簡(jiǎn)單實(shí)現(xiàn)示例:2016-06-06
python 使用socket傳輸圖片視頻等文件的實(shí)現(xiàn)方式
這篇文章主要介紹了python 使用socket傳輸圖片視頻等文件的實(shí)現(xiàn)方式,本文給出了實(shí)例代碼,需要的朋友可以參考下2019-08-08
一行代碼實(shí)現(xiàn)Python動(dòng)態(tài)加載依賴
本文主要介紹了Python動(dòng)態(tài)加載依賴,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
Python3之讀取連接過的網(wǎng)絡(luò)并定位的方法
下面小編就為大家分享一篇Python3之讀取連接過的網(wǎng)絡(luò)并定位的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04
python常用函數(shù)random()函數(shù)詳解
這篇文章主要介紹了python常用函數(shù)random()函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02
Python input函數(shù)使用實(shí)例解析
這篇文章主要介紹了Python input函數(shù)使用實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Python實(shí)現(xiàn)的HTTP并發(fā)測(cè)試完整示例
python二維列表一維列表的互相轉(zhuǎn)換實(shí)例

