關(guān)于python的進程,常用的庫有兩個:multiprocessing和subprocess模塊。
具體使用時,想要實現(xiàn)并發(fā)調(diào)用外部指令背镇,應該用哪個模塊呢?
研究下兩個模塊區(qū)別:
multiprocessing的核心機制是fork泽裳,重開一個進程瞒斩,首先會把父進程的代碼copy重載一遍,但是在windows平臺上是不支持fork的涮总,那windows上如何使用呢胸囱?
--答案是,if main入口中瀑梗,就可以照常使用multiprocessing(忘記為啥了/試出來的)烹笔;
subprocess適用于與外部進程交互,調(diào)用外部進程抛丽;
那么谤职,如下場景:pc連接手機,想要持續(xù)捕捉手機adb日志铺纽,然后啟動一個app進程柬帕,如何實現(xiàn)哟忍?
首先狡门,如果使用multiprocessing:
//#coding=utf-8
from multiprocessing import Process
import os
myCmd1='adb logcat -v time>c:/log/ll.txt'
myCmd2='adb shell monkey -p com.yoosal.kanku -s 500 --ignore-crashes --ignore-timeouts --monitor-native-crashes --bugreport --throttle 1000 -v -v -v 100000'
//子進程要執(zhí)行的代碼
def run_proc1(name):
os.system(myCmd1)
def run_proc2():
os.system(myCmd2)
if name== 'main':
p1 = Process(target=run_proc1,args=('test',))
p2 = Process(target=run_proc2)
p1.start()
p2.start()
p1.join()
p2.join()
print('Child process end.')
運行結(jié)果:可正常并行進程1、進程2
如果使用subprocess:
import os
import subprocess
myCmd1='adb logcat -v time>c:/log/ll.txt'
myCmd2='adb shell monkey -p com.yoosal.kanku -s 500 --ignore-crashes --ignore-timeouts --monitor-native-crashes --bugreport --throttle 1000 -v -v -v 100000'
child1=subprocess.Popen(myCmd1, shell=True,stdout=None)
child2=subprocess.Popen(myCmd2, shell=True,stdout=None)
運行結(jié)果:可正常并行進程1锅很、進程2
由此可見其馏,multiprocessing也能用于執(zhí)行外部指令,他們的區(qū)別呢爆安?叛复??求解
自己查到的答案是:
subprocess 用來執(zhí)行外部命令扔仓,是os.fork() 和 os.execve() 的封裝褐奥,即先fork一個子進程,再運行新的外部程序翘簇,子進程不會把父進程的模塊加載一遍撬码;
而multiprocessing的原理是fork,fork()調(diào)用:調(diào)用1次版保,返回兩次--操作系統(tǒng)自動把當前進程(父進程)復制了一份(子進程)呜笑,然后夫否,分別在父進程和子進程內(nèi)返回,父進程返回子進程的pid叫胁,子進程返回0凰慈,即父進程和子進程都在運行。
對于外部調(diào)用來說驼鹅,使用multiprocessing太占資源微谓。
這里又有另外一個問題:multiprocessing中,調(diào)用p.join()等待子進程執(zhí)行結(jié)束输钩,subprocess模塊--父進程如何監(jiān)聽子進程結(jié)束堰酿?
兩個方法:
subprocess.Popen()父進程開啟子進程后,不管其是否結(jié)束张足,直接執(zhí)行下一步触创;
subprocess.Call()父進程一直等待到子進程運行結(jié)束,再執(zhí)行下一步为牍;
現(xiàn)在一種場景:父進程中使用subprocess.Popen()開啟了3個子進程哼绑,要等到3個子進程全部結(jié)束后,父進程再執(zhí)行下一步碉咆,如何處理抖韩?
沒有找到可以在父進程里,直接一個方法可以判斷所有子進程是否結(jié)束的方法疫铜,那么常規(guī)方法就是自己做判斷咯:
//監(jiān)聽子進程是否結(jié)束茂浮,結(jié)束則返回True
def listen_to_child(ss):
i=0
while True:
if ss[i].poll()!=None: //poll返回碼:0 正常結(jié)束;1 sleep壳咕;
//2 子進程不存在席揽;-15 kill;None run
i=i+1
if i>=len(ss):
return True
`