日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python的进程模块

發(fā)布時間:2024/9/15 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的进程模块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 進程與線程
    • 進程定義:
    • 線程定義
    • 線程進程的關(guān)系區(qū)別
      • 1.直接調(diào)用
      • 2.繼承式調(diào)用
      • 3.threading.thread實例方法
          • join() :
            • 情況1:
            • 情況2:
          • Daemon() :守護線程
    • 同步鎖
    • 死鎖和遞歸鎖
    • 事件event
    • 信號量(控制同時可以運行的線程)
  • 隊列——多線程利器
    • 創(chuàng)建一個“隊列”對象
    • 生產(chǎn)者消費者模型
  • 多進程模塊multiprocessing
    • 每秒鐘運行3個
    • show the individual process IDs involved
    • Process類
    • 進程間通信
      • 通過隊列
      • 通過管道
      • 信息共享 manager

進程與線程

假如有兩個程序A和B,程序A在執(zhí)行到一半的過程中,需要讀取大量的數(shù)據(jù)輸入(I/O操作),而此時CPU只能靜靜地等待任務A讀取完數(shù)據(jù)才能繼續(xù)執(zhí)行,這樣就白白浪費了CPU資源。是不是在程序A讀取數(shù)據(jù)的過程中,讓程序B去執(zhí)行,當程序A讀取完數(shù)據(jù)之后,讓程序B暫停,然后讓程序A繼續(xù)執(zhí)行?當然沒問題,但這里有一個關(guān)鍵詞:切換。
切換,那么這就涉及到了狀態(tài)的保存,狀態(tài)的恢復,加上程序A與程序B所需要的系統(tǒng)資源(內(nèi)存,硬盤,鍵盤等等)是不一樣的。自然而然的就需要有一個東西去記錄程序A和程序B分別需要什么資源,怎樣去識別程序A和程序B等等,所以就有了一個叫進程的抽象。

進程定義:

進程就是一個程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行過程。
進程一般由程序、數(shù)據(jù)集、進程控制塊三部分組成。

舉一例說明進程:
想象一位有一手好廚藝的計算機科學家正在為他的女兒烘制生日蛋糕。他有做生日蛋糕的食譜,廚房里有所需
的原料:面粉、雞蛋、糖、香草汁等。在這個比喻中,做蛋糕的食譜就是程序(即用適當形式描述的算法)計算機科學家就是處理器(cpu),
而做蛋糕的各種原料就是輸入數(shù)據(jù)。進程就是廚師閱讀食譜、取來各種原料以及烘制蛋糕等一系列動作的總和。
現(xiàn)在假設計算機科學家的兒子哭著跑了進來,說他的頭被一只蜜蜂蟄了。計算機科學家就記錄下他
照著食譜做到哪兒了(保存進程的當前狀態(tài)),然后拿出一本急救手冊,按照其中的指示處理蟄傷。這
里,我們看到處理機從一個進程(做蛋糕)切換到另一個高優(yōu)先級的進程(實施醫(yī)療救治),每個進程
擁有各自的程序(食譜和急救手冊)。當蜜蜂蟄傷處理完之后,這位計算機科學家又回來做蛋糕,從他
離開時的那一步繼續(xù)做下去。

線程定義

線程的出現(xiàn)是為了降低上下文切換的消耗,提高系統(tǒng)的并發(fā)性,并突破一個進程只能干一樣事的缺陷,
使到進程內(nèi)并發(fā)成為可能。

假設,一個文本程序,需要接受鍵盤輸入,將內(nèi)容顯示在屏幕上,還需要保存信息到硬盤中。若只有
一個進程,勢必造成同一時間只能干一樣事的尷尬(當保存時,就不能通過鍵盤輸入內(nèi)容)。若有多
個進程,每個進程負責一個任務,進程A負責接收鍵盤輸入的任務,進程B負責將內(nèi)容顯示在屏幕上的
任務,進程C負責保存內(nèi)容到硬盤中的任務。這里進程A,B,C間的協(xié)作涉及到了進程通信問題,而且
有共同都需要擁有的東西-------文本內(nèi)容,不停的切換造成性能上的損失。若有一種機制,可以使
任務A,B,C共享資源,這樣上下文切換所需要保存和恢復的內(nèi)容就少了,同時又可以減少通信所帶
來的性能損耗,那就好了。是的,這種機制就是線程。

線程也叫輕量級進程,它是一個基本的CPU執(zhí)行單元,也是程序執(zhí)行過程中的最小單元,由線程ID、程序
計數(shù)器、寄存器集合和堆棧共同組成。線程的引入減小了程序并發(fā)執(zhí)行時的開銷,提高了操作系統(tǒng)的并發(fā)
性能。線程沒有自己的系統(tǒng)資源。

線程進程的關(guān)系區(qū)別

1.Threads share the address space of the process that created it; processes have their own address space. 線程共享創(chuàng)建它的進程的地址空間;進程們有它們各自的地址空間 2.Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process. 線程們可以直接訪問它的進程數(shù)據(jù);進程們有它們父進程的數(shù)據(jù)拷貝 3.Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes. 線程能夠直接與其進程的其他線程交流;進程間的交流需要用交互進程才能與他們的近鄰進程交流 4.New threads are easily created; new processes require duplication of the parent process. 新縣城能容易創(chuàng)建;新進程需要復制父進程 5.Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes. 線程可以在同一進程的線程上執(zhí)行大量操作;進程只能作業(yè)于子進程 6.Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes. 對主線程的改變(取消,權(quán)限變更等...)可能會影響同一進程的其他線程的表現(xiàn);對父進程的改變不會影響子進程

1.一個程序至少有一個進程,一個進程至少有一個線程.(進程可以理解成線程的容器)
2.進程在執(zhí)行過程中擁有獨立的內(nèi)存單元,而多個線程共享內(nèi)存,從而極大地提高了程序的運行效率。
3.線程在執(zhí)行過程中與進程還是有區(qū)別的。每個獨立的線程有一個程序運行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨立執(zhí)行,必須依存在應用程序中,由應用程序提供多個線程執(zhí)行控制。
4.進程是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位.
5.線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧)但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
6.一個線程可以創(chuàng)建和撤銷另一個線程;同一個進程中的多個線程之間可以并發(fā)執(zhí)行.

python的GIL

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

上面的核心意思就是,無論你啟多少個線程,你有多少個cpu, Python在執(zhí)行的時候會淡定的在同一時刻只允許一個線程運行

python的線程和threading模塊

線程調(diào)用的兩種模式:直接調(diào)用、繼承式調(diào)用

1.直接調(diào)用

import threading import timedef speaksth(num):#定義函數(shù)用于線程運行print('start running threading%d' %num)time.sleep(num)if __name__=='__main__':t1 = threading.Thread(target=speaksth,args=(1,))#生成一個線程實例t2 = threading.Thread(target=speaksth,args=(2,))#生成另一個線程實例t1.start()t2.start()print(t1.getName())#獲取線程名print(t2.getName()) # 獲取線程名print('end'.center(20,'-'))

2.繼承式調(diào)用

import threading import timeclass m_thread(threading.Thread):def __init__(self,num,time):self.num = numself.time= timethreading.Thread.__init__(self)def run(self):#定義每個線程的運行函數(shù)print('running on num:%s' %self.num)time.sleep(self.time)print('num:%s end'.center(20,'^') %self.num)if __name__ == '__main__':t1 = m_thread(1,3)t2 = m_thread(2,5)t1.start()t2.start()print("main threading end".center(20,'-'))

3.threading.thread實例方法

.join()要加在線程.start()之后,先線程1.start()主線程一碰到 線程1.join()就停下來等待。

join() :

在子線程完成運行之前,這個子線程的父線程將一直被阻塞。在這個線程運行結(jié)束之前,其他線程等待。

情況1:
import threading from time import ctime,sleep import timedef ListenMusic(name):print("begin listening to %s. %s" %(name,ctime()))sleep(3)print("end listening %s"%ctime()) def RecordBlog(title):print("Begin recording the %s %s" %(title,ctime()))sleep(5)print("end recording %s"%ctime())threads = [] for i in range(5):threads.append(threading.Thread(target=ListenMusic,args=(str(i),)))if __name__ == '__main__':for t in threads:t.start()t.join()print("End main thread %s"%ctime())


即,一個運行完再到另一個

情況2:
import threading from time import ctime,sleep import time def ListenMusic(name):print("begin listening to %s. %s" %(name,ctime()))sleep(3)print("end listening %s"%ctime()) def RecordBlog(title):print("Begin recording the %s %s" %(title,ctime()))sleep(5)print("end recording %s"%ctime())threads = [] for i in range(5):threads.append(threading.Thread(target=ListenMusic,args=(str(i),)))if __name__ == '__main__':for t in threads:t.start()#t.join()print("End main thread %s"%ctime())

Daemon() :守護線程

setDaemon(True):
將線程聲明為守護線程,必須在start() 方法調(diào)用之前設置, 如果不設置為守護線程程序會被無限掛起。這個方法基本和join是相反的。 當我們在程序運行中,執(zhí)行一個主線程,如果主線程又創(chuàng)建一個子線程,主線程和子線程就分兵兩路,分別運行,那么當主線程完成想退出時,會檢驗子線程是否完成。如果子線程未完成,則主線程會等待子線程完成后再退出。但是有時候我們需要的是只要主線程完成了,不管子線程是否完成,都要和主線程一起退出,這時就可以用setDaemon方法啦
例子:

import threading from time import ctime,sleep import time def ListenMusic(name):print("begin listening to %s. %s" %(name,ctime()))sleep(3)print("end listening %s"%ctime()) def RecordBlog(title):print("Begin recording the %s %s" %(title,ctime()))sleep(5)print("end recording %s"%ctime()) threads = [] for i in range(5):threads.append(threading.Thread(target=ListenMusic,args=(str(i),)))if __name__ == '__main__':for t in threads:t.setDaemon(True) #一定要在start之前設置t.start()print("End main thread %s"%ctime())

一瞬間執(zhí)行完畢,不等子線程運行完成。

同步鎖

import time import threading def addNum():global num #在每個線程中都獲取這個全局變量#num-=1temp=num#print('--get num:',num )time.sleep(0.1)num =temp-1 #對此公共變量進行-1操作num = 100 #設定一個共享變量 thread_list = [] for i in range(100):t = threading.Thread(target=addNum)t.start()thread_list.append(t)for t in thread_list: #等待所有線程執(zhí)行完畢t.join()print('final num:', num )


改變time.sleep()的時間

import time import threading def addNum():global num #在每個線程中都獲取這個全局變量#num-=1temp=num#print('--get num:',num )time.sleep(0.0001)num =temp-1 #對此公共變量進行-1操作num = 100 #設定一個共享變量 thread_list = [] for i in range(100):t = threading.Thread(target=addNum)t.start()thread_list.append(t)for t in thread_list: #等待所有線程執(zhí)行完畢t.join()print('final num:', num )


鎖原理圖:
當time.sleep(0.1)變化時 /0.001/0.0000001
多個線程都在同時操作同一個共享資源,所以造成了資源破壞,怎么辦呢?(join會造成串行,失去所線程的意義)

我們可以通過同步鎖來解決這種問題

import time import threading R = threading.Lock()# 同步鎖 def addNum():global num #在每個線程中都獲取這個全局變量#num-=1R.acquire()#獲取鎖temp=num#print('--get num:',num )time.sleep(0.0001)num =temp-1 #對此公共變量進行-1操作R.release()#解鎖num = 100 #設定一個共享變量 thread_list = [] for i in range(100):t = threading.Thread(target=addNum)t.start()thread_list.append(t)for t in thread_list: #等待所有線程執(zhí)行完畢t.join()print('final num:', num )

死鎖和遞歸鎖

事件event

An event is a simple synchronization object;the event represents an internal flag,

and threads can wait for the flag to be set, or set or clear the flag themselves.
event = threading.Event()

a client thread can wait for the flag to be set
event.wait()

a server thread can set or reset it
event.set()
event.clear()

If the flag is set, the wait method doesn’t do anything.
If the flag is cleared, wait will block until it becomes set again.
Any number of threads may wait for the same event.

import threading,time class Boss(threading.Thread):def run(self):print('老板發(fā)話了嗎?',event_ganhuo.isSet())# Falsetime.sleep(1)print("BOSS:今晚大家都要加班到22:00。")event_ganhuo.set()print('老板發(fā)話了嗎?',event_ganhuo.isSet())# Truetime.sleep(5)print('老板說下班了嗎?',event_xiaban.isSet())# Falsetime.sleep(1)print("BOSS:<22:00>可以下班了。")event_xiaban.set()print('老板說下班了嗎?',event_xiaban.isSet())# Trueclass Worker(threading.Thread):def run(self):event_ganhuo.wait()# 一旦event被設定,等同于passtime.sleep(1)print("Worker:哎……命苦啊!")time.sleep(1)event_xiaban.wait()time.sleep(1)print("Worker:OhYeah!")if __name__=="__main__":event_ganhuo=threading.Event()event_xiaban=threading.Event()threads=[]for i in range(5):threads.append(Worker())threads.append(Boss())for t in threads:t.start()for t in threads:t.join()print("ending.....")

運行結(jié)果:

信號量(控制同時可以運行的線程)

信號量用來控制線程并發(fā)數(shù)的,BoundedSemaphore或Semaphore管理一個內(nèi)置的計數(shù) 器,每當調(diào)用acquire()時-1,調(diào)用release()時+1。

import threading,time class myThread(threading.Thread):def run(self):if semaphore.acquire():print(self.name)time.sleep(2)semaphore.release() if __name__=="__main__":semaphore=threading.Semaphore(5)#每次能運行的線程thrs=[]for i in range(100):thrs.append(myThread())for t in thrs:t.start()

線程每隔2秒出現(xiàn)5個

隊列——多線程利器

保證線程安全。
有線程隊列也有進程隊列

創(chuàng)建一個“隊列”對象

import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue類即是一個隊列的同步實現(xiàn)。隊列長度可為無限或者有限。可通過Queue的構(gòu)造函數(shù)的可選參數(shù)maxsize來設定隊列長度。如果maxsize小于1就表示隊列長度無限。

將一個值放入隊列中
q.put(10)
調(diào)用隊列對象的put()方法在隊尾插入一個項目。put()有兩個參數(shù),第一個item為必需的,為插入項目的值;第二個block為可選參數(shù),默認為
1。如果隊列當前為空且block為1,put()方法就使調(diào)用線程暫停,直到空出一個數(shù)據(jù)單元。如果block為0,put方法將引發(fā)Full異常。

將一個值從隊列中取出
q.get()
調(diào)用隊列對象的get()方法從隊頭刪除并返回一個項目。可選參數(shù)為block,默認為True。如果隊列為空且block為True,
get()就使調(diào)用線程暫停,直至有項目可用。如果隊列為空且block為False,隊列將引發(fā)Empty異常。

Python Queue模塊有三種隊列及構(gòu)造函數(shù):
1、Python Queue模塊的FIFO隊列先進先出。 class queue.Queue(maxsize)
2、LIFO類似于堆,即先進后出。 class queue.LifoQueue(maxsize)
3、還有一種是優(yōu)先級隊列級別越低越先出來。 class queue.PriorityQueue(maxsize)

此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回隊列的大小
q.empty() 如果隊列為空,返回True,反之False
q.full() 如果隊列滿了,返回True,反之False
q.full 與 maxsize 大小對應
q.get([block[, timeout]]) 獲取隊列,timeout等待時間
q.get_nowait() 相當q.get(False)
非阻塞 q.put(item) 寫入隊列,timeout等待時間
q.put_nowait(item) 相當q.put(item, False)
q.task_done() 在完成一項工作之后,q.task_done() 函數(shù)向任務已經(jīng)完成的隊列發(fā)送一個信號
q.join() 實際上意味著等到隊列為空,再執(zhí)行別的操作

import queue import time q = queue.Queue(3) #創(chuàng)建隊列默認first in first out,只能存3個隊列q.put(12) q.put('hello') q.put({'name':'AFf'}) #q.put(34) #再加這一步會一直卡住,因為只能有3個 #q.put(34,False) #不會卡住,但是報錯while 1:data = q.get(block=False)#隊列為空時,取不出則報錯time.sleep(1)print(data)

優(yōu)先級隊列

import queue import time q = queue.PriorityQueue() #創(chuàng)建隊列默認first in first out,只能存3個隊列 q.put([3,12]) q.put([2,'hello']) q.put([4,{'name':'AFf'}]) #q.put(34) #再加這一步會一直卡住,因為只能有3個 #q.put(34,False) #不會卡住,但是報錯while 1:data = q.get()#隊列為空時,取不出則報錯time.sleep(1)print(data)

生產(chǎn)者消費者模型

import queue,threading import time import random q = queue.Queue()def Producer(name):count = 0while count<5:print('begin produce bread')count += 1print('\033[32;1m%s has produced %d bread\033[0m'%(name,count))time.sleep(2)q.put(count)print('round end'.center(20,'-'))def Consumer(name):data = 0while data<5:time.sleep(random.randint(1,2))if q.qsize()>0:print('begin eat bread'.center(20,'^'))data = q.get()print('%s has eat a bread')else:print("-----no baozi anymore----")p1 = threading.Thread(target=Producer,args=('abc',)) c1 = threading.Thread(target=Consumer,args=('guest',)) p1.start() c1.start()

多進程模塊multiprocessing

Multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency,effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.

每秒鐘運行3個

from multiprocessing import Process import time def f(name):time.sleep(1)print('hello', name,time.ctime())if __name__ == '__main__':p_list=[]for i in range(3):for j in range(3):p = Process(target=f, args=('alvin',))p_list.append(p)p.start()for i in p_list:p.join()print('end')

show the individual process IDs involved

from multiprocessing import Process import os import timedef info(title):print("title:", title)print('parent process:', os.getppid())print('process id:', os.getpid())def f(name):info('function f')print('hello', name)if __name__ == '__main__':info('main process line')time.sleep(1)print("------------------")p = Process(target=info, args=('yuan',))p.start()p.join()

Process類

構(gòu)造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
  group: 線程組,目前還沒有實現(xiàn),庫引用中提示必須是None;
  target: 要執(zhí)行的方法;
  name: 進程名;
  args/kwargs: 要傳入方法的參數(shù)。
實例方法:
  is_alive():返回進程是否在運行。
  join([timeout]):阻塞當前上下文環(huán)境的進程程,直到調(diào)用此方法的進程終止或到達指定的timeout(可選參數(shù))。
  start():進程準備就緒,等待CPU調(diào)度
  run():strat()調(diào)用run方法,如果實例進程時未制定傳入target,這star執(zhí)行t默認run()方法。
  terminate():不管任務是否完成,立即停止工作進程
屬性:
  daemon:和線程的setDeamon功能一樣
  name:進程名字。
  pid:進程號。

import time from multiprocessing import Process class MyProcess(Process):def __init__(self,num):super(MyProcess,self).__init__()#繼承父類的初始化字段self.num = numdef run(self):time.sleep(1)print(self.pid)print(p.is_alive())print(self.num)time.sleep(1)if __name__ == '__main__':p_list=[]for i in range(10):p = MyProcess(i)#p.daemon=Truep_list.append(p)for p in p_list:p.start()print('main process end')

進程間通信

通過隊列

import time # #import queue #進程間的通信不能用線程隊列 import multiprocessing def foo(q):time.sleep(1)print("son process",id(q))#打印q的idq.put(123)q.put("yuan") if __name__ == '__main__':#q=queue.Queue()q=multiprocessing.Queue()p=multiprocessing.Process(target=foo,args=(q,))#傳一個進程隊列q過去p.start()#p.join()print("main process",id(q))print(q.get())print(q.get())

通過管道

from multiprocessing import Process, Pipe def f(conn):conn.send([12, {"name":"yuan"}, 'hello'])response=conn.recv()print("response",response)conn.close()print("q_ID2:",id(conn))if __name__ == '__main__':parent_conn, child_conn = Pipe() #雙向管道print("q_ID1:",id(child_conn))p = Process(target=f, args=(child_conn,))p.start()print(parent_conn.recv()) #父進程等待,如果沒有收到將會阻塞, prints "[42, None, 'hello']"parent_conn.send("兒子你好!")p.join()

信息共享 manager

from multiprocessing import Process, Manager def f(d, l,n):d[n] = '1' #{0:"1"}d['2'] = 2 #{0:"1","2":2}l.append(n) #[0,1,2,3,4, 0,1,2,3,4,5,6,7,8,9]#print(l)if __name__ == '__main__':with Manager() as manager:d = manager.dict()#{}l = manager.list(range(5))#[0,1,2,3,4]p_list = []for i in range(10):p = Process(target=f, args=(d,l,i))p.start()p_list.append(p)for res in p_list:res.join()print(d)print(l)

參考鏈接:
http://www.cnblogs.com/yuanchenqi/articles/6248025.html

總結(jié)

以上是生活随笔為你收集整理的python的进程模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。