python進程管理
『壹』 python中進程與線程的區別是什麼
Num01–>線程
線程是操作系統中能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。
一個線程指的是進程中一個單一順序的控制流。
一個進程中可以並發多條線程,每條線程並行執行不同的任務。
Num02–>進程
進程就是一個程序在一個數據集上的一次動態執行過程。
進程有以下三部分組成:
1,程序:我們編寫的程序用來描述進程要完成哪些功能以及如何完成。
2,數據集:數據集則是程序在執行過程中需要的資源,比如圖片、音視頻、文件等。
3,進程式控制制塊:進程式控制制塊是用來記錄進程的外部特徵,描述進程的執行變化過程,系統可以用它來控制和管理進程,它是系統感知進程存在的唯一標記。
Num03–>進程和線程的區別:
1、運行方式不同:
進程不能單獨執行,它只是資源的集合。
進程要操作CPU,必須要先創建一個線程。
所有在同一個進程里的線程,是同享同一塊進程所佔的內存空間。
2,關系
進程中第一個線程是主線程,主線程可以創建其他線程;其他線程也可以創建線程;線程之間是平等的。
進程有父進程和子進程,獨立的內存空間,唯一的標識符:pid。
3,速度
啟動線程比啟動進程快。
運行線程和運行進程速度上是一樣的,沒有可比性。
線程共享內存空間,進程的內存是獨立的。
4,創建
父進程生成子進程,相當於復制一份內存空間,進程之間不能直接訪問
創建新線程很簡單,創建新進程需要對父進程進行一次復制。
一個線程可以控制和操作同級線程里的其他線程,但是進程只能操作子進程。
5,交互
同一個進程里的線程之間可以直接訪問。
兩個進程想通信必須通過一個中間代理來實現。
相關推薦:《Python視頻教程》
Num04–>幾個常見的概念
1,什麼的並發和並行?
並發:微觀上CPU輪流執行,宏觀上用戶看到同時執行。因為cpu切換任務非常快。
並行:是指系統真正具有同時處理多個任務(動作)的能力。
2,同步、非同步和輪詢的區別?
同步任務:B一直等著A,等A完成之後,B再執行任務。(打電話案例)
輪詢任務:B沒有一直等待A,B過一會來問一下A,過一會問下A
非同步任務:B不需要一直等著A, B先做其他事情,等A完成後A通知B。(發簡訊案例)
Num05–>進程和線程的優缺點比較
首先,要實現多任務,通常我們會設計Master-Worker模式,Master負責分配任務,Worker負責執行任務,因此,多任務環境下,通常是一個Master,多個Worker。
如果用多進程實現Master-Worker,主進程就是Master,其他進程就是Worker。
如果用多線程實現Master-Worker,主線程就是Master,其他線程就是Worker。
多進程模式最大的優點就是穩定性高,因為一個子進程崩潰了,不會影響主進程和其他子進程。(當然主進程掛了所有進程就全掛了,但是Master進程只負責分配任務,掛掉的概率低)著名的Apache最早就是採用多進程模式。
多進程模式的缺點是創建進程的代價大,在Unix/linux系統下,用fork調用還行,在Windows下創建進程開銷巨大。另外,操作系統能同時運行的進程數也是有限的,在內存和CPU的限制下,如果有幾千個進程同時運行,操作系統連調度都會成問題。
多線程模式通常比多進程快一點,但是也快不到哪去,而且,多線程模式致命的缺點就是任何一個線程掛掉都可能直接造成整個進程崩潰,因為所有線程共享進程的內存。在Windows上,如果一個線程執行的代碼出了問題,你經常可以看到這樣的提示:「該程序執行了非法操作,即將關閉」,其實往往是某個線程出了問題,但是操作系統會強制結束整個進程。
在Windows下,多線程的效率比多進程要高,所以微軟的IIS伺服器默認採用多線程模式。由於多線程存在穩定性的問題,IIS的穩定性就不如Apache。為了緩解這個問題,IIS和Apache現在又有多進程+多線程的混合模式,真是把問題越搞越復雜。
Num06–>計算密集型任務和IO密集型任務
是否採用多任務的第二個考慮是任務的類型。我們可以把任務分為計算密集型和IO密集型。
第一種:計算密集型任務的特點是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視頻進行高清解碼等等,全靠CPU的運算能力。這種計算密集型任務雖然也可以用多任務完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計算密集型任務同時進行的數量應當等於CPU的核心數。
計算密集型任務由於主要消耗CPU資源,因此,代碼運行效率至關重要。Python這樣的腳本語言運行效率很低,完全不適合計算密集型任務。對於計算密集型任務,最好用C語言編寫。
第二種:任務的類型是IO密集型,涉及到網路、磁碟IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低於CPU和內存的速度)。對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,比如Web應用。
IO密集型任務執行期間,99%的時間都花在IO上,花在CPU上的時間很少,因此,用運行速度極快的C語言替換用Python這樣運行速度極低的腳本語言,完全無法提升運行效率。對於IO密集型任務,最合適的語言就是開發效率最高(代碼量最少)的語言,腳本語言是首選,C語言最差。
相關推薦:
Python中的進程是什麼
『貳』 python 多進程 進程池子進程結束怎麼獲取
在利用Python進行系統管理的時候,特別是同時操作多個文件目錄,或者遠程式控制制多台主機,並行操作可以節約大量的時間。當被操作對象數目不大時,可以直接利用multiprocessing中的Process動態成生多個進程,10幾個還好,但如果是上百個,上千個目標,手動的去限制進程數量卻又太過繁瑣,這時候進程池Pool發揮作用的時候就到了。
Pool可以提供指定數量的進程,供用戶調用,當有新的請求提交到pool中時,如果池還沒有滿,那麼就會創建一個新的進程用來執行該請求;但如果池中的進程數已經達到規定最大值,那麼該請求就會等待,直到池中有進程結束,才會創建新的進程來它。這里有一個簡單的例子:
#!/usr/bin/env python
#coding=utf-8
"""
Author: Squall
Last modified: 2011-10-18 16:50
Filename: pool.py
Description: a simple sample for pool class
"""
from multiprocessing import Pool
from time import sleep
def f(x):
for i in range(10):
print '%s --- %s ' % (i, x)
sleep(1)
def main():
pool = Pool(processes=3) # set the processes max number 3
for i in range(11,20):
result = pool.apply_async(f, (i,))
pool.close()
pool.join()
if result.successful():
print 'successful'
if __name__ == "__main__":
main()
先創建容量為3的進程池,然後將f(i)依次傳遞給它,運行腳本後利用ps aux | grep pool.py查看進程情況,會發現最多隻會有三個進程執行。pool.apply_async()用來向進程池提交目標請求,pool.join()是用來等待進程池中的worker進程執行完畢,防止主進程在worker進程結束前結束。但必pool.join()必須使用在pool.close()或者pool.terminate()之後。其中close()跟terminate()的區別在於close()會等待池中的worker進程執行結束再關閉pool,而terminate()則是直接關閉。result.successful()表示整個調用執行的狀態,如果還有worker沒有執行完,則會拋出AssertionError異常。
利用multiprocessing下的Pool可以很方便的同時自動處理幾百或者上千個並行操作,腳本的復雜性也大大降低。
『叄』 python 多線程與多進程問題
監控一個信號就起一個線程與進程處理。這樣的邏輯是不太合適的。所有的資源都是有限的,如果這樣浪費很快會資源管理失控。
常規的做法是起一個線程池,或者是進程池。 使用線程還是進程取決於你處理的信號的類型。如果計算量大,則需要進程池,如果只是設備等待,比如網路數據收發,則線程也勉強夠用。
信號過來後處理方法有兩種,一種是實時處理,這個沒有好辦法,可以用「微線程」的辦法做,盡量減少處理周期。另外一種是允許少量的延遲。那麼通常的做法是用隊列。將信號放到線程或者是進程池的消息隊列里。然後再由後者分配。
還有一種高效的處理方法,根據信號的值做hash,然後自動分發到不同的CPU或者是伺服器。這個就算是大規模並發處理機制。
通常情況下,比如一個WEB伺服器,它需要獲取一個請求,然後處理響應,可以使用線程模型,或者是進程模型。也是使用典型的池的方法。一個Pool的大於,取決於你的計算 機的計算 能力,內存大小,以及你的並發訪問數量。
所要要啟用多少個呢?假設你的一個信號的處理周期是1秒,你同時有100個信號進來,那麼就需要100個線程或者是進程。
線程數過多,表面上處理能力在增加,不過延遲也在增加,失敗率也會增加。
『肆』 python怎麼讓進程暫停
如果在linux運行,就跟普通程序一樣就行,查找pid,然後使用kill。如果實在windows,ctrl+alt+delete,打開任務管理器,查找進程,然後結束掉就可以了。
『伍』 python怎麼實現一個進程
想要充分利用多核CPU資源,Python中大部分情況下都需要使用多進程,Python中提供了multiprocessing這個包實現多進程。multiprocessing支持子進程、進程間的同步與通信,提供了Process、Queue、Pipe、Lock等組件。
開辟子進程
multiprocessing中提供了Process類來生成進程實例
Process([group [, target [, name [, args [, kwargs]]]]])1
group分組,實際上不使用
target表示調用對象,你可以傳入方法的名字
args表示給調用對象以元組的形式提供參數,比如target是函數a,他有兩個參數m,n,那麼該參數為args=(m, n)即可
kwargs表示調用對象的字典
name是別名,相當於給這個進程取一個名字
- # -*- coding:utf-8 -*-from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):
- n = 0
- while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime()) #獲取當前進程號和正在運行是的時間
- time.sleep(wTime) #等待(休眠)
- n += 1if __name__ == "__main__":
- p = Process(target=run_proc, args=(2,)) #申請子進程
- p.start() #運行進程
- print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())12345678910111213141516171819
- # -*- coding:utf-8 -*-from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):
- n = 0
- while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
- time.sleep(wTime)
- n += 1if __name__ == "__main__":
- p = Process(target=run_proc, args=(2,))
- p.daemon = True #加入daemon
- p.start() print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())
- # -*- coding:utf-8 -*-from multiprocessing import Process, Poolimport osimport timedef run_proc(wTime):
- n = 0
- while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
- time.sleep(wTime)
- n += 1if __name__ == "__main__":
- p = Process(target=run_proc, args=(2,))
- p.daemon = True
- p.start()
- p.join() #加入join方法
- print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())21
- # -*- coding:utf-8 -*-from multiprocessing import Process, Poolimport osimport timeclass Myprocess(Process):
- def __init__(self, wTime):
- Process.__init__(self)
- self.wTime = wTime def run(self):
- n = 0
- while n < 3: print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
- time.sleep(self.wTime)
- n += 1if __name__ == "__main__":
- p = Myprocess(2)
- p.daemon = True
- p.start() #自動調用run方法
- p.join() print "Parent process run. subProcess is ", p.pid print "Parent process end,{0}".format(time.ctime())2122232425262728
- # -*- coding:utf-8 -*-from multiprocessing import Process,Poolimport os,timedef run_proc(name): ##定義一個函數用於進程調用
- for i in range(5):
- time.sleep(0.2) #休眠0.2秒
- print 'Run child process %s (%s)' % (name, os.getpid())#執行一次該函數共需1秒的時間if __name__ =='__main__': #執行主進程
- print 'Run the main process (%s).' % (os.getpid())
- mainStart = time.time() #記錄主進程開始的時間
- p = Pool(8) #開辟進程池
- for i in range(16): #開辟14個進程
- p.apply_async(run_proc,args=('Process'+str(i),))#每個進程都調用run_proc函數,
- #args表示給該函數傳遞的參數。
- print 'Waiting for all subprocesses done ...'
- p.close() #關閉進程池
- p.join() #等待開辟的所有進程執行完後,主進程才繼續往下執行
- print 'All subprocesses done'
- mainEnd = time.time() #記錄主進程結束時間
- print 'All process ran %0.2f seconds.' % (mainEnd-mainStart) #主進程執行時間21222324
先來個小例子:
運行結果:
Parent process run. subProcess is 30196
Parent process end,Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:23 2017
subProcess 30196 run, Mon Mar 27 11:20:25 2017
根據運行結果可知,父進程運行結束後子進程仍然還在運行,這可能造成僵屍( zombie)進程。
通常情況下,當子進程終結時,它會通知父進程,清空自己所佔據的內存,並在內核里留下自己的退出信息。父進程在得知子進程終結時,會從內核中取出子進程的退出信息。但是,如果父進程早於子進程終結,這可能造成子進程的退出信息滯留在內核中,子進程成為僵屍(zombie)進程。當大量僵屍進程積累時,內存空間會被擠占。
有什麼辦法可以避免僵屍進程呢?
這里介紹進程的一個屬性 deamon,當其值為TRUE時,其父進程結束,該進程也直接終止運行(即使還沒運行完)。
所以給上面的程序加上p.deamon = true,看看效果。
執行結果:
Parent process run. subProcess is 31856
Parent process end,Mon Mar 27 11:40:10 2017
這是問題又來了,子進程並沒有執行完,這不是所期望的結果。有沒辦法將子進程執行完後才讓父進程結束呢?
這里引入p.join()方法,它使子進程執行結束後,父進程才執行之後的代碼
執行結果:
subProcess 32076 run, Mon Mar 27 11:46:07 2017
subProcess 32076 run, Mon Mar 27 11:46:09 2017
subProcess 32076 run, Mon Mar 27 11:46:11 2017
Parent process run. subProcess is 32076
Parent process end,Mon Mar 27 11:46:13 2017
這樣所有的進程就能順利的執行了。
將進程定義成類
通過繼承Process類,來自定義進程類,實現run方法。實例p通過調用p.start()時自動調用run方法。
如下:
執行結果和上一個例子相同。
創建多個進程
很多時候系統都需要創建多個進程以提高CPU的利用率,當數量較少時,可以手動生成一個個Process實例。當進程數量很多時,或許可以利用循環,但是這需要程序員手動管理系統中並發進程的數量,有時會很麻煩。這時進程池Pool就可以發揮其功效了。可以通過傳遞參數限制並發進程的數量,默認值為CPU的核數。
直接上例子:
執行結果:
開頭部分
Run the main process (30920).
Waiting for all subprocesses done …
Run child process Process0 (32396)
Run child process Process3 (25392)
Run child process Process1 (28732)
Run child process Process2 (32436)
末尾部分:
Run child process Process15 (25880)
All subprocesses done
All process last 2.49 seconds.
相關說明:
這里進程池對並發進程的限制數量為8個,而程序運行時會產生16個進程,進程池將自動管理系統內進程的並發數量,其餘進程將會在隊列中等待。限制並發數量是因為,系統中並發的進程不是越多越好,並發進程太多,可能使CPU大部分的時間用於進程調度,而不是執行有效的計算。
採用多進程並發技術時,就單個處理機而言,其對進程的執行是串列的。但具體某個時刻哪個進程獲得CPU資源而執行是不可預知的(如執行結果的開頭部分,各進程的執行順序不定),這就體現了進程的非同步性。
如果單個程序執行14次run_proc函數,那麼它會需要至少16秒,通過進程的並發,這里只需要2.49秒,可見並發的優勢。
『陸』 如何判斷並殺掉超時的python進程
supervisord專門乾的就是這事,這個已經很成熟,伺服器上的Python和MongoDB進程都是用它管理的。 如果supervisord還不滿足你的需求,如你需要在自己的程序中進行進程管理,你可以去參考supervisord的代碼實現。 簡單的,可以自己用 http://docs.python.org/library/subprocess.html去實現自己的一套。
『柒』 如何讓 Python 代碼常駐在伺服器進程中
一、nohup
nohup,即 no hangup,nohup 的用途就是讓提交的命令忽略 hangup 信號,從而使我們的進程避免中途被中斷。它可以讓 python 腳本和伺服器連接端的 session 分離,以達到退出後依舊執行:
$ chmod +x /your_path/yourscript.py # 先設置可執行許可權$ nohup python /your_path/yourscript.py# 切記退出的 Terminal 的時候,不要 ctrl+c 退出,而是直接關閉,不然 Nohup 就被你關閉了。
如何關閉這個一直執行的進程呢:
# 找到對應的進程 PID
$ ps -ef | grep python
# 返回內容如:
user 2430 1 0 Jul03 ? 00:00:01 /usr/bin/python -tt /usr/sbin/yum-updatesd
# kill 掉該進程即可:
$ kill -9 2430
PS:nohup 在伺服器重啟之後就失效了,所以並不完美。
二、將命令寫入 Linux 啟動腳本
Linux 在啟動的時候會執行 /etc/rc.local 裡面的腳本,所以只要在這里添加執行命令就可以:
$ vim /etc/rc.local
# 如果是 Centos 添加以下內容:
/your_path/python3.4 /your_path/yourscript.py
# 以上內容需要添加在 exit 命令前,而且由於在執行 rc.local 腳本時,PATH 環境變數未全部初始化,因此命令需要使用絕對路徑。
PS:這種方式的缺點是如果腳本掛了,那麼不會自動重新啟動。
三、使用 Supervisor 進程管理工具
詳見這篇文章:使用 Supervisor 管理伺服器後台進程,在伺服器重啟和腳本出錯後,可以完美重啟,推薦。
『捌』 python 關閉正在運行的python進程
打開任務管理器(右鍵任務欄)關閉
『玖』 python怎麼獲取自身進程的CPU和內存使用情況
這個需要進進程管理查看 如何打開進程管理器 快捷鍵Ctrl+Alt+方向鍵下鍵(或者小鍵盤的Enter鍵)
『拾』 如何使用Python的Supervisor來管理進程
在python開發中,如何使用supervisor來管理進程呢?Supervisor是什麼?Supervisor是如何管理進程的,現在就跟隨小編一起來看看使用python的supervisor管理經常的方法。
Supervisor可以啟動、停止、重啟*nix系統中的程序。也可以重啟崩潰的程序。
supervisord的一個守護進程,用於將指定的進程當做子進程來運行。
supervisorctl是一個客戶端程序,可以查看日誌並通過統一的會話來控制進程。
看例子:
我們寫了一個py腳本,用於往log文件中記錄一條當前的時間。
[python]view plain
1.root@ubuntu:/home/zoer#catdaemon.py
2.#!/usr/bin/envpython
3.
4.importtime
5.importos
6.time.sleep(1)
7.f=open("log",'a')
8.t=time.time()
9.f.write(str(t))
10.f.write("\n")
11.f.close()
安裝過程就不說了。
安裝完畢supervisor之後【將配置文件放在/etc下】。修改配置文件,在最後增加如下內容:
[program:ddd]
command=/home/zoer/daemon.py
autorestart=true
然後我們啟動supervisor並啟動daemon.py的執行。
[python]view plain
1.root@ubuntu:/home/zoer#supervisord
2./usr/local/lib/python2.7/dist-packages/supervisor-3.0b1-py2.7.egg/supervisor/options.py:286:UserWarning:aultlocations();youprobablywanttospecifya"-c"y.
3.''
4.root@ubuntu:/home/zoer#supervisorctl
5.dddSTARTING
6.supervisor>startddd
7.ddd:ERROR(alreadystarted)
8.supervisor>stopddd
9.ddd:stopped
10.supervisor>startddd
11.ddd:started
12.supervisor>
從上面的例子中,看到,可以通過start或者stop命令來啟動或者停止ddd這個進程。ddd這里就是我們在配置文件中增加的內容(daemon.py這個腳本)。
也可以使用restart。如下:
supervisor> restart ddd
ddd: stopped
ddd: started
-------------------------------------------------------
下面我們測試一下,假設說我們手動kill掉了ddd這個進程,那麼ddd會自動恢復執行嗎?
為了做實驗,把代碼修改如下:
[python]view plain
1.root@ubuntu:/home/zoer#catdaemon.py
2.#!/usr/bin/envpython
3.
4.importtime
5.importos
6.whileTrue:
7.time.sleep(1)
8.f=open("log",'a')
9.t=time.time()
10.f.write(str(t))
11.f.write("\n")
12.f.close()
通過ps可以找到這個進程的id:
[plain]view plain
1.root93540.20.4109244200?S23:160:00python/home/zoer/daemon.py
2.root93950.00.04392832pts/3S+23:170:00grep--color=autodaemon
3.root@ubuntu:/home/zoer#
看下面的操作:
[plain]view plain
1.root@ubuntu:/home/zoer#rmlog;touchlog;kill9354
2.root@ubuntu:/home/zoer#catlog
3.1364710712.51
4.root@ubuntu:/home/zoer#catlog
5.1364710712.51
6.1364710713.51
7.root@ubuntu:/home/zoer#catlog
8.1364710712.51
9.1364710713.51
10.root@ubuntu:/home/zoer#catlog
11.1364710712.51
12.1364710713.51
13.1364710714.52
14.root@ubuntu:/home/zoer#catlog
15.1364710712.51
16.1364710713.51
17.1364710714.52
18.1364710715.52
刪除了log文件,並且重新創建。然後幹掉了daemon.py的那個進程。會發現log內容又重新有新的內容了。再次ps查看進程號。
[plain]view plain
1.root94290.10.4109244200?S23:180:00python/home/zoer/daemon.py
2.root94400.00.04392828pts/3S+23:190:00grep--color=autodaemon
3.root@ubuntu:/home/zoer#
會發現進程號已經變成9429了。說明supervisor已經重啟了被幹掉了的進程。