python進程id
A. python 多進程
基於官方文檔:
https://docs.python.org/zh-cn/3/library/multiprocessing.html
日樂購,剛才看到的一個博客,寫的都不太對,還是基於官方的比較穩妥
我就是喜歡抄官方的,哈哈
通常我們使用Process實例化一個進程,並調用 他的 start() 方法啟動它。
這種方法和 Thread 是一樣的。
上圖中,我寫了 p.join() 所以主進程是 等待 子進程執行完後,才執行 print("運行結束")
否則就是反過來了(這個不一定,看你的語句了,順序其實是隨機的)例如:
主進加個 sleep
所以不加join() ,其實子進程和主進程是各干各的,誰也不等誰。都執行完後,文件運行就結束了
上面我們用了 os.getpid() 和 os.getppid() 獲取 當前進程,和父進程的id
下面就講一下,這兩個函數的用法:
os.getpid()
返回當前進程的id
os.getppid()
返回父進程的id。 父進程退出後,unix 返回初始化進程(1)中的一個
windows返回相同的id (可能被其他進程使用了)
這也就解釋了,為啥我上面 的程序運行多次, 第一次列印的parentid 都是 14212 了。
而子進程的父級 process id 是調用他的那個進程的 id : 1940
視頻筆記:
多進程:使用大致方法:
參考: 進程通信(pipe和queue)
pool.map (函數可以有return 也可以共享內存或queue) 結果直接是個列表
poll.apply_async() (同map,只不過是一個進程,返回結果用 xx.get() 獲得)
報錯:
參考 : https://blog.csdn.net/xiemanR/article/details/71700531
把 pool = Pool() 放到 if name == " main ": 下面初始化搞定。
結果:
這個肯定有解釋的
測試多進程計算效果:
進程池運行:
結果:
普通計算:
我們同樣傳入 1 2 10 三個參數測試:
其實對比下來開始快了一半的;
我們把循環里的數字去掉一個 0;
單進程:
多進程:
兩次測試 單進程/進程池 分別為 0.669 和 0.772 幾乎成正比的。
問題 二:
視圖:
post 視圖裡面
Music 類:
直接報錯:
寫在 類裡面也 在函數里用 self.pool 調用也不行,也是相同的錯誤。
最後 把 pool = Pool 直接寫在 search 函數裡面,奇跡出現了:
前台也能顯示搜索的音樂結果了
總結一點,進程這個東西,最好 寫在 直接運行的函數裡面,而不是 一個函數跳來跳去。因為最後可能 是在子進程的子進程運行的,這是不許的,會報錯。
還有一點,多進程運行的函數對象,不能是 lambda 函數。也許lambda 虛擬,在內存??
使用 pool.map 子進程 函數報錯,導致整個 pool 掛了:
參考: https://blog.csdn.net/hedongho/article/details/79139606
主要你要,對函數內部捕獲錯誤,而不能讓異常拋出就可以了。
關於map 傳多個函數參數
我一開始,就是正常思維,多個參數,搞個元祖,讓參數一一對應不就行了:
報錯:
參考:
https://blog.csdn.net/qq_15969343/article/details/84672527
普通的 process 當讓可以穿多個參數,map 卻不知道咋傳的。
apply_async 和map 一樣,不知道咋傳的。
最簡單的方法:
使用 starmap 而不是 map
結果:
子進程結束
1.8399453163146973
成功拿到結果了
關於map 和 starmap 不同的地方看源碼:
關於apply_async() ,我沒找到多參數的方法,大不了用 一個迭代的 starmap 實現。哈哈
關於 上面源碼裡面有 itertools.starmap
itertools 用法參考:
https://docs.python.org/zh-cn/3/library/itertools.html#itertool-functions
有個問題,多進程最好不要使用全部的 cpu , 因為這樣可能影響其他任務,所以 在進程池 添加 process 參數 指定,cpu 個數:
上面就是預留了 一個cpu 干其他事的
後面直接使用 Queue 遇到這個問題:
解決:
Manager().Queue() 代替 Queue()
因為 queue.get() 是堵塞型的,所以可以提前判斷是不是 空的,以免堵塞進程。比如下面這樣:
使用 queue.empty() 空為True
B. 一篇文章帶你深度解析Python線程和進程
使用Python中的線程模塊,能夠同時運行程序的不同部分,並簡化設計。如果你已經入門Python,並且想用線程來提升程序運行速度的話,希望這篇教程會對你有所幫助。
線程與進程
什麼是進程
進程是系統進行資源分配和調度的一個獨立單位 進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。每個進程都有自己的獨立內存空間,不同進程通過進程間通信來通信。由於進程比較重量,占據獨立的內存,所以上下文進程間的切換開銷(棧、寄存器、虛擬內存、文件句柄等)比較大,但相對比較穩定安全。
什麼是線程
CPU調度和分派的基本單位 線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。線程間通信主要通過共享內存,上下文切換很快,資源開銷較少,但相比進程不夠穩定容易丟失數據。
進程與線程的關系圖
線程與進程的區別:
進程
現實生活中,有很多的場景中的事情是同時進行的,比如開車的時候 手和腳共同來駕駛 汽車 ,比如唱歌跳舞也是同時進行的,再比如邊吃飯邊打電話;試想如果我們吃飯的時候有一個領導來電,我們肯定是立刻就接聽了。但是如果你吃完飯再接聽或者回電話,很可能會被開除。
注意:
多任務的概念
什麼叫 多任務 呢?簡單地說,就是操作系統可以同時運行多個任務。打個比方,你一邊在用瀏覽器上網,一邊在聽MP3,一邊在用Word趕作業,這就是多任務,至少同時有3個任務正在運行。還有很多任務悄悄地在後台同時運行著,只是桌面上沒有顯示而已。
現在,多核CPU已經非常普及了,但是,即使過去的單核CPU,也可以執行多任務。由於CPU執行代碼都是順序執行的,那麼,單核CPU是怎麼執行多任務的呢?
答案就是操作系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒,這樣反復執行下去。表面上看,每個任務都是交替執行的,但是,由於CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。
真正的並行執行多任務只能在多核CPU上實現,但是,由於任務數量遠遠多於CPU的核心數量,所以,操作系統也會自動把很多任務輪流調度到每個核心上執行。 其實就是CPU執行速度太快啦!以至於我們感受不到在輪流調度。
並行與並發
並行(Parallelism)
並行:指兩個或兩個以上事件(或線程)在同一時刻發生,是真正意義上的不同事件或線程在同一時刻,在不同CPU資源呢上(多核),同時執行。
特點
並發(Concurrency)
指一個物理CPU(也可以多個物理CPU) 在若幹道程序(或線程)之間多路復用,並發性是對有限物理資源強制行使多用戶共享以提高效率。
特點
multiprocess.Process模塊
process模塊是一個創建進程的模塊,藉助這個模塊,就可以完成進程的創建。
語法:Process([group [, target [, name [, args [, kwargs]]]]])
由該類實例化得到的對象,表示一個子進程中的任務(尚未啟動)。
注意:1. 必須使用關鍵字方式來指定參數;2. args指定的為傳給target函數的位置參數,是一個元祖形式,必須有逗號。
參數介紹:
group:參數未使用,默認值為None。
target:表示調用對象,即子進程要執行的任務。
args:表示調用的位置參數元祖。
kwargs:表示調用對象的字典。如kwargs = {'name':Jack, 'age':18}。
name:子進程名稱。
代碼:
除了上面這些開啟進程的方法之外,還有一種以繼承Process的方式開啟進程的方式:
通過上面的研究,我們千方百計實現了程序的非同步,讓多個任務可以同時在幾個進程中並發處理,他們之間的運行沒有順序,一旦開啟也不受我們控制。盡管並發編程讓我們能更加充分的利用IO資源,但是也給我們帶來了新的問題。
當多個進程使用同一份數據資源的時候,就會引發數據安全或順序混亂問題,我們可以考慮加鎖,我們以模擬搶票為例,來看看數據安全的重要性。
加鎖可以保證多個進程修改同一塊數據時,同一時間只能有一個任務可以進行修改,即串列的修改。加鎖犧牲了速度,但是卻保證了數據的安全。
因此我們最好找尋一種解決方案能夠兼顧:1、效率高(多個進程共享一塊內存的數據)2、幫我們處理好鎖問題。
mutiprocessing模塊為我們提供的基於消息的IPC通信機制:隊列和管道。隊列和管道都是將數據存放於內存中 隊列又是基於(管道+鎖)實現的,可以讓我們從復雜的鎖問題中解脫出來, 我們應該盡量避免使用共享數據,盡可能使用消息傳遞和隊列,避免處理復雜的同步和鎖問題,而且在進程數目增多時,往往可以獲得更好的可獲展性( 後續擴展該內容 )。
線程
Python的threading模塊
Python 供了幾個用於多線程編程的模塊,包括 thread, threading 和 Queue 等。thread 和 threading 模塊允許程序員創建和管理線程。thread 模塊 供了基本的線程和鎖的支持,而 threading 供了更高級別,功能更強的線程管理的功能。Queue 模塊允許用戶創建一個可以用於多個線程之間 共享數據的隊列數據結構。
python創建和執行線程
創建線程代碼
1. 創建方法一:
2. 創建方法二:
進程和線程都是實現多任務的一種方式,例如:在同一台計算機上能同時運行多個QQ(進程),一個QQ可以打開多個聊天窗口(線程)。資源共享:進程不能共享資源,而線程共享所在進程的地址空間和其他資源,同時,線程有自己的棧和棧指針。所以在一個進程內的所有線程共享全局變數,但多線程對全局變數的更改會導致變數值得混亂。
代碼演示:
得到的結果是:
首先需要明確的一點是GIL並不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。就好比C++是一套語言(語法)標准,但是可以用不同的編譯器來編譯成可執行代碼。同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行(其中的JPython就沒有GIL)。
那麼CPython實現中的GIL又是什麼呢?GIL全稱Global Interpreter Lock為了避免誤導,我們還是來看一下官方給出的解釋:
主要意思為:
因此,解釋器實際上被一個全局解釋器鎖保護著,它確保任何時候都只有一個Python線程執行。在多線程環境中,Python 虛擬機按以下方式執行:
由於GIL的存在,Python的多線程不能稱之為嚴格的多線程。因為 多線程下每個線程在執行的過程中都需要先獲取GIL,保證同一時刻只有一個線程在運行。
由於GIL的存在,即使是多線程,事實上同一時刻只能保證一個線程在運行, 既然這樣多線程的運行效率不就和單線程一樣了嗎,那為什麼還要使用多線程呢?
由於以前的電腦基本都是單核CPU,多線程和單線程幾乎看不出差別,可是由於計算機的迅速發展,現在的電腦幾乎都是多核CPU了,最少也是兩個核心數的,這時差別就出來了:通過之前的案例我們已經知道,即使在多核CPU中,多線程同一時刻也只有一個線程在運行,這樣不僅不能利用多核CPU的優勢,反而由於每個線程在多個CPU上是交替執行的,導致在不同CPU上切換時造成資源的浪費,反而會更慢。即原因是一個進程只存在一把gil鎖,當在執行多個線程時,內部會爭搶gil鎖,這會造成當某一個線程沒有搶到鎖的時候會讓cpu等待,進而不能合理利用多核cpu資源。
但是在使用多線程抓取網頁內容時,遇到IO阻塞時,正在執行的線程會暫時釋放GIL鎖,這時其它線程會利用這個空隙時間,執行自己的代碼,因此多線程抓取比單線程抓取性能要好,所以我們還是要使用多線程的。
GIL對多線程Python程序的影響
程序的性能受到計算密集型(CPU)的程序限制和I/O密集型的程序限制影響,那什麼是計算密集型和I/O密集型程序呢?
計算密集型:要進行大量的數值計算,例如進行上億的數字計算、計算圓周率、對視頻進行高清解碼等等。這種計算密集型任務雖然也可以用多任務完成,但是花費的主要時間在任務切換的時間,此時CPU執行任務的效率比較低。
IO密集型:涉及到網路請求(time.sleep())、磁碟IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低於CPU和內存的速度)。對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。
當然為了避免GIL對我們程序產生影響,我們也可以使用,線程鎖。
Lock&RLock
常用的資源共享鎖機制:有Lock、RLock、Semphore、Condition等,簡單給大家分享下Lock和RLock。
Lock
特點就是執行速度慢,但是保證了數據的安全性
RLock
使用鎖代碼操作不當就會產生死鎖的情況。
什麼是死鎖
死鎖:當線程A持有獨占鎖a,並嘗試去獲取獨占鎖b的同時,線程B持有獨占鎖b,並嘗試獲取獨占鎖a的情況下,就會發生AB兩個線程由於互相持有對方需要的鎖,而發生的阻塞現象,我們稱為死鎖。即死鎖是指多個進程因競爭資源而造成的一種僵局,若無外力作用,這些進程都將無法向前推進。
所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配演算法,避免進程永久占據系統資源。
死鎖代碼
python線程間通信
如果各個線程之間各干各的,確實不需要通信,這樣的代碼也十分的簡單。但這一般是不可能的,至少線程要和主線程進行通信,不然計算結果等內容無法取回。而實際情況中要復雜的多,多個線程間需要交換數據,才能得到正確的執行結果。
python中Queue是消息隊列,提供線程間通信機制,python3中重名為為queue,queue模塊塊下提供了幾個阻塞隊列,這些隊列主要用於實現線程通信。
在 queue 模塊下主要提供了三個類,分別代表三種隊列,它們的主要區別就在於進隊列、出隊列的不同。
簡單代碼演示
此時代碼會阻塞,因為queue中內容已滿,此時可以在第四個queue.put('蘋果')後面添加timeout,則成為 queue.put('蘋果',timeout=1)如果等待1秒鍾仍然是滿的就會拋出異常,可以捕獲異常。
同理如果隊列是空的,無法獲取到內容默認也會阻塞,如果不阻塞可以使用queue.get_nowait()。
在掌握了 Queue 阻塞隊列的特性之後,在下面程序中就可以利用 Queue 來實現線程通信了。
下面演示一個生產者和一個消費者,當然都可以多個
使用queue模塊,可在線程間進行通信,並保證了線程安全。
協程
協程,又稱微線程,纖程。英文名Coroutine。
協程是python個中另外一種實現多任務的方式,只不過比線程更小佔用更小執行單元(理解為需要的資源)。為啥說它是一個執行單元,因為它自帶CPU上下文。這樣只要在合適的時機, 我們可以把一個協程 切換到另一個協程。只要這個過程中保存或恢復 CPU上下文那麼程序還是可以運行的。
通俗的理解:在一個線程中的某個函數,可以在任何地方保存當前函數的一些臨時變數等信息,然後切換到另外一個函數中執行,注意不是通過調用函數的方式做到的,並且切換的次數以及什麼時候再切換到原來的函數都由開發者自己確定。
在實現多任務時,線程切換從系統層面遠不止保存和恢復 CPU上下文這么簡單。操作系統為了程序運行的高效性每個線程都有自己緩存Cache等等數據,操作系統還會幫你做這些數據的恢復操作。所以線程的切換非常耗性能。但是協程的切換只是單純的操作CPU的上下文,所以一秒鍾切換個上百萬次系統都抗的住。
greenlet與gevent
為了更好使用協程來完成多任務,除了使用原生的yield完成模擬協程的工作,其實python還有的greenlet模塊和gevent模塊,使實現協程變的更加簡單高效。
greenlet雖說實現了協程,但需要我們手工切換,太麻煩了,gevent是比greenlet更強大的並且能夠自動切換任務的模塊。
其原理是當一個greenlet遇到IO(指的是input output 輸入輸出,比如網路、文件操作等)操作時,比如訪問網路,就自動切換到其他的greenlet,等到IO操作完成,再在適當的時候切換回來繼續執行。
模擬耗時操作:
如果有耗時操作也可以換成,gevent中自己實現的模塊,這時候就需要打補丁了。
使用協程完成一個簡單的二手房信息的爬蟲代碼吧!
以下文章來源於Python專欄 ,作者宋宋
文章鏈接:https://mp.weixin.qq.com/s/2r3_ipU3HjdA5VnqSHjUnQ
C. Python實現多進程+進度條顯示
之前在寫繁體字轉簡體字的時候,由於數據量比較大,所以用了多進程來實現。其實我對多進程/多線程的認識只是了解概念,第一次看到實際的應用是在BDCI-OCR的項目中,作者用多進程進行圖像處理。毫無疑問,並行計算能顯著地減少運行時間。
那麼為什麼用多進程實現並行計算(多核任務),不用多線程呢?
引用鏈接
網上有很多實現多進程的示例,我只記錄自己用過的。
這里我用的是pool.apply_async(),是非同步非阻塞的方法,可以理解為:不用等待當前進程執行完畢,隨時根據系統調度來進行進程切換。當然,還有其他方法,網上有很多資料,我就不贅述了。
從運行結果中可以發現:因為cpu最大核心數是8,所以前8個任務的進程id都不一樣,任務9的進程id與任務2的相同,即任務2執行結束後再執行任務9,依此類推。
模擬的事件:共需處理10個任務,每個任務執行時間為5秒(5 * time.sleep(1))
參考鏈接
發現:因為我的cpu是8核,所以10個任務的多進程耗時約為 2×單任務耗時 。
在查閱相關資料時發現,多進程在實際使用的時候有 單參數 和 多參數 之分,那麼多參數和單參數的優缺點分別是什麼呢?
D. python殺進程cpu滿了
如果你的Python程序佔用了過多的CPU資源,可能是因為它在執行某些操作時出現了問題。要解決這個問題,你可以嘗試以下步驟:
1. 找出佔用CPU資源的進程的PID(進程ID):可以在命令行中使用`top`或`htop`命令,或者在Windows系統中使用任務管理器碰配。
2. 使用`kill`命令結束該進程:在命令行中輸入`kill PID`,其中PID是笑行指進程ID。如果進程仍然無法結束,可以使用`kill -9 PID`強制結束進程。
3. 如果你的Python程序在執行某些操作時出現了問題,可以嘗試對代碼進行優化,或者使用一些工具來診斷和解決問題,如`cProfile`、`line_profiler`等。
4. 如果你的Python程序需要長時間運行,可以考慮使用多進程或多線程帶陵來提高性能,或者使用一些優化工具來優化代碼。
E. python 獲取進程的pid
方法一:
使用subprocess 的check_output函數執行pidof命令
方法二:
使用pgrep命令,pgrep獲取的結果與pidof獲得的結果稍有不同.pgrep的孝手改進程id稍多幾個.pgrep命令可以使適用subprocess的check_out函數執行
方法三:
獲取當前腳本的pid進程
方法四:命令獲取+kill PID
說明:
注意:linux的進程號最大是是 32768 (32 位系統)和 2 的 22 次方(400w 左右)(64 位系統)。cut -c 9-15不夠巧判薯喚,改成awk '{print $2}'
F. python腳本怎麼獲取遠程linux伺服器的進程名
進程信息
/proc目錄包含了所有正運行的進程目錄。這些目錄的名字和進程的標識符是一樣的。所以,如果你遍歷/proc目錄下那些使用數字作為它們的名字的目錄,你就會獲得所有現在正在運行的進程列表。在下面的代碼中process_list()函數返回所有現在正在運行的進程的標識符列表。當你執行這個程序後,這個列表的長度就是在系統上運行的總進程數。
復制代碼 代碼如下:
#!/usr/bin/env python
"""
List of all process IDs currently active
"""
from __future__ import print_function
import os
def process_list():
pids = []
for subdir in os.listdir('/proc'):
if subdir.isdigit():
pids.append(subdir)
return pids
if __name__=='__main__':
pids = process_list()
print('Total number of running processes:: {0}'.format(len(pids)))
上面的程序當執行後會顯示和下面類似的輸出:
復制代碼 代碼如下:
Total number of running processes:: 229
每個進程目錄包含了一些其他文件和目錄,如進程命令的調用,它正使用的共享庫以及其它的。
建議看看《Linux就該這么學》這本書
G. python怎麼獲得進程的pid
#-*-encoding:UTF-8-*-
importos
importsys
importstring
importpsutil
importre
defget_pid(name):
process_list=psutil.get_process_list()
regex="pid=(d+),sname='"+name+"'"
printregex
pid=0
forlineinprocess_list:
process_info=str(line)
ini_regex=re.compile(regex)
result=ini_regex.search(process_info)
ifresult!=None:
pid=string.atoi(result.group(1))
printresult.group()
break
defmain(argv):<br>name=argv[1]<br>get_pid(name)
if__name__=="__main__":
main(sys.argv)
H. python命令看不懂,求解釋
python /usr/lib/python2.7/site-packages/vnc_cfg_api_server/vnc_cfg_api_server.py --logging_level=DEBUG --conf_file /etc/contrail/api_server.conf &
這段意思是在後台執行一個路徑下的python腳本,腳本名為vnc_cfg_api_server.py,中間是設置日誌級別以及配置文件的路徑
echo $! >/opt/stack/status/contrail/apiSrv.pid; fg || echo "apiSrv failed to start" | tee "/opt/stack/status/contrail/apiSrv.failure"^M
這段意思是將運行在後台最後的一個進程id寫入到apiSrv.pid文件中,或者列印"apiSrv failed to start"並且將錯誤信息寫入到apiSrv.failure文件中
另外解釋幾個shell中的幾個符號:
$! 是在後台運行的最後的工作的PID(進程ID)
& 是後台運行的一個命令
|| 是或操作符
| 是管道符
^M這個應該你打開的文件是一個linux下的文件,在window會有個這個符號。
整體的意思是執行腳本之前把最後運行的id寫入到一個文件中,如果有錯誤,則列印出來並且也寫入到一個文件,隨後執行那個python腳本
I. linux 後台python程序
你已經將程序在後台運行了啊,我覺得你是搞錯御雀州了一個概念,在後台運行並不代表程序不能輸出內容到終端啊,你不想屏幕上顯示,重定向輸出就完了。
python3 abc >null &
然後,另一個問題,為什麼ctrl c沒有歲培用,這個快捷鍵只對前台運行的程序有效!你程序都在後台運行了,當然沒用咯。程序轉到後台鎮蔽時會提示JOB ID的,比如「[1] 4226」,JOB ID是1,進程ID是4226。
查看當前有哪些JOB在運行,可以通過jobs命令來實現,比如:
[root@localhost]#jobs-l
[1]+4347運行中python3main.py>null&
一般我用到的命令就是bg和fg,fg(foreground的意思)命令可以將後台運行的job換到前台,比如fg 1就能把上面顯示的python3 main.py > null &換到前台執行。
J. 求教一個問題 python卡住
在IDLE上跑一個py干數知了嘩枯點壞事,把x-window搞死了
趕緊GOOGLE,解決方法:
ctrl+alt+F1(~F6)到一個TTY界面,輸入帳號密碼,登錄進系統。
輸入:ps -A |grep "python"
找到了亂畢洞IDLE的進程ID
輸入:kill -9 6644
6644是IDLE的進程ID
幹掉來IDLE,把它的子進程也連帶一快幹掉了。
按ctrl+alt+F7,回到x-window