標籤:同步 linux ddr address sub 添加 output 執行 如何
多任務實現的3種方式:
多進程模式
多線程模式
多進程+多線程模式
線程是最小的執行單元,而進程由至少一個線程組成。
多進程(multiprocessing)
Unix/linux用fork()函數,調用一次返回兩個值,子進程永遠返回0,夫進程返回子進程的ID。
子進程調用getppid()函數就可以拿到夫進程的ID。
Unix/Linux建立子進程
import osprint("Process(%s) start..." %os.getpip())pid = os.fork() #windows上沒有fork調用if pid == 0: print("I am child process (%s) and my parent is %s" %(os.getpid(), os.getppid()))else: print("I (%s) just created a child process (%s)" %(os.getpid(),pid))
multiprocessing:跨平台多進程
multiprocessing模組提供了Process類來代表一個進程對象
from multiprocessing import Processimport osdef run_proc(name): print("Run child process %s(%s)" %(name, os.getpid()))if __name__ == "__main__": print("Parent process %s." %os.getpid()) p = Process(target=run_proc, args=(‘test‘,)) #建立子進程,傳入一個執行函數和執行函數的參數 print("Child process will start.") p.start() #啟動子進程 p.join() #等待子進程結束再繼續往下運行,用於進程間的同步 print("Child process end.")
執行結果:
Parent process 928.Process will start.Run child process test (929)...Process end.
Pool:進程池,大量建立子進程
from multiprocessing import Poolimport os, time, randomdef long_time_task(name): print("Run task %s(%s)..." %(name, os.getpid())) start = time.time() time.sleep(random.random()*3) end = time.time() print("Task %s runs %0.2f seconds." %(name, (end-start)))if __name__ == "__main__": print("Parent process %s." %os.getpid()) p = Pool(4) for i in range(5): p.apply_async(long_time_task, args=(i, )) print("Waiting for all subprocess done...") p.close() p.join() print("All subprocess done.")
執行結果:
Parent process 4756.Waiting for all subprocess done...Run task 0(3920)...Run task 1(1688)...Run task 2(2996)...Run task 3(3132)...Task 1 runs 0.32 seconds.Run task 4(1688)...Task 2 runs 0.61 seconds.Task 3 runs 1.41 seconds.Task 4 runs 2.26 seconds.Task 0 runs 2.89 seconds.All subprocess done.
分析:
對Pool對象調用join()方法會等待所有子進程執行完畢,調用join()之前必須先調用close(),調用close()之後就不能繼續添加新的Process了。
請注意輸出的結果,task 0,1,2,3是立刻執行的,而task 4要等待前面某個task完成後才執行,這是因為Pool的預設大小在我的電腦上是4,因此,最多同時執行4個進程。這是Pool有意設計的限制,並不是作業系統的限制
子進程(subprocess)
subprocess模組可以讓我們非常方便地啟動一個子進程,然後控制其輸入和輸出
import subprocess#下面的例子示範了如何在Python代碼中運行命令nslookup www.python.org,這和命令列直接啟動並執行效果是一樣的:print("$ nslookup www.python.rog")r = subprocess.call(["nslookup", "www.python.org"])print("Exit code:", r)
運行結果:
$ nslookup www.python.orgServer: 192.168.19.4Address: 192.168.19.4#53Non-authoritative answer:www.python.org canonical name = python.map.fastly.net.Name: python.map.fastly.netAddress: 199.27.79.223Exit code: 0
如果子進程還需要輸入,則可通過communicate()方法輸入:
import subprocessprint(‘$ nslookup‘)p = subprocess.Popen([‘nslookup‘], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)output, err = p.communicate(b‘set q=mx\npython.org\nexit\n‘)print(output.decode(‘utf-8‘))print(‘Exit code:‘, p.returncode)
處理序間通訊
Process之間肯定是需要通訊的,作業系統提供了很多機制來實現進程間的通訊。Python的multiprocessing模組封裝了底層的機制,提供了Queue、Pipes等多種方式來交換資料
以Queue為例,在父進程中建立兩個子進程,一個往Queue裡寫資料,一個從Queue裡讀資料:
from multiprocessing import Process, Queueimport os, time, random# 寫資料進程執行的代碼:def write(q): print(‘Process to write: %s‘ % os.getpid()) for value in [‘A‘, ‘B‘, ‘C‘]: print(‘Put %s to queue...‘ % value) q.put(value) time.sleep(random.random())# 讀資料進程執行的代碼:def read(q): print(‘Process to read: %s‘ % os.getpid()) while True: value = q.get(True) print(‘Get %s from queue.‘ % value)if __name__==‘__main__‘: # 父進程建立Queue,並傳給各個子進程: q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 啟動子進程pw,寫入: pw.start() # 啟動子進程pr,讀取: pr.start() # 等待pw結束: pw.join() # pr進程裡是死迴圈,無法等待其結束,只能強行終止: pr.terminate()
執行結果:
Process to write: 3872Put A to queue...Process to read: 4756Get A from queue.Put B to queue...Get B from queue.Put C to queue...Get C from queue.
Python:進程