Python多進程(三)——進程間通信 & Queue隊列

進程間通信

      全局變量在多個進程中不共享,進程之間的數據是獨立的,默認情況下互不影響
 

from multiprocessing import Process

num=1

def work1():
	global num
	num+=5
	print('子進程 1 運行, num:',num)

def work2():
	global num
	num += 10
	print('子進程 2 運行, num: ',num)

if __name__=='__main__':
	print('父進程開始運行')
	p1=Process(target=work1)
	p2=Process(target=work2)
	p1.start()
	p2.start()
	p1.join()
	p2.join()

 

用 Queue 實現多進程之間的數據傳遞

      Queue 是多進程安全的隊列,可以使用 Queue 實現多進程之間的數據傳遞。

      put 方法用以插入數據到隊列中, put 方法還有兩個可選參數: blocked 和 timeout。如果 blocked 爲 True(默認值),並且 timeout 爲正值,該方法會阻塞 timeout 指定的時間,直到該隊列有剩餘的空間。如果超時,會拋出 Queue.full 異常。如果 blocked 爲 False,但該 Queue 已滿,會立即拋出 Queue.full 異常。

      get 方法可以從隊列讀取並且刪除一個元素。同樣, get 方法有兩個可選參數: blocked和 timeout。如果 blocked 爲 True(默認值),並且 timeout 爲正值,那麼在等待時間內沒有取到任何元素,會拋出 Queue.Empty 異常。如果 blocked 爲 False,有兩種情況存在,如果Queue 有一個值可用,則立即返回該值,否則,如果隊列爲空,則立即拋出Queue.Empty 異常
 

from multiprocessing import Queue

q=Queue(3)
q.put('消息 1')
q.put('消息 2')
print('消息隊列是否已滿: ',q.full())
q.put('消息 3')
print('消息隊列是否已滿: ',q.full())
#q.put('消息 4')因爲消息隊列已滿,需要直接寫入需要等待,如果超時會拋出異常,

#所以寫入時候需判斷,消息隊列是否已滿
if not q.full():
	q.put('消息 4')

#同理讀取消息時,先判斷消息隊列是否爲空,再讀取
if not q.empty():
	for i in range(q.qsize()):
		print(q.get())

 

Queue 隊列實現進程間通信

from multiprocessing import *
import time

def write(q):
	#將列表中的元素寫入隊列中
	for i in ["a","b","c"]:
		print('開始寫入值%s' % i)
		q.put(i)
		time.sleep(1)

#讀取
def read(q):
	print('開始讀取')
	while True:
		if not q.empty():
			print('讀取到:',q.get())
			time.sleep(1)
		else:
			break

if __name__=='__main__':
	#創建隊列
	q=Queue()
	#創建寫入進程
	pw=Process(target=write,args=(q,))
	pr=Process(target=read,args=(q,))
	#啓動進程
	pw.start()
	pw.join()
	pr.start()
	pr.join()

 

        如果使用 Pool 創建進程,就需要使用 multiprocessing.Manager()中的 Queue()來完成進程間的通信,而不是 multiprocessing.Queue(),否則會拋出異常

from multiprocessing import Manager,Pool
import time

def write(q):
	#將列表中的元素寫入隊列中
	for i in ["a","b","c"]:
		print('開始寫入值%s' % i)
		q.put(i)
		time.sleep(1)

#讀取
def read(q):
	print('開始讀取')
	while True:
		if not q.empty():
			print('讀取到:',q.get())
			time.sleep(1)
		else:
			break

if __name__=='__main__':
	#創建隊列
	q=Manager().Queue()
	#創建進程池
	p=Pool(3)
	#使用apply阻塞模式創建進程
	p.apply(write,(q,))
	p.apply(read,(q,))
	p.close()
	p.join()

 

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