Python的os模块封装了常⻅的系统调⽤,其中就包括fork,可以在Python程序中轻松创建⼦进程:
程序执⾏到os.fork()时,操作系统会创建⼀个新的进程(⼦进程),然后复制⽗进程的所有信息到⼦进程中然后⽗进程和⼦进程都会从fork()函数中得到⼀个返回值,在⼦进程中这个值⼀定是0,⽽⽗进程中是⼦进程的 id号
但是由于Windows没有fork调⽤,难道在Windows上⽆法⽤Python编写多进程的程序?
Python是跨平台的,⾃然提供了⼀个跨平台的多进程⽀持。multiprocessing模块就是跨平台版本的多进程模块。
第一种:multiprocessing
#coding=utf-8
from multiprocessing import Process
import os
# ⼦进程要执⾏的代码
def run_proc(name):
print('⼦进程运⾏中,name= %s ,pid=%d...' % (name, os.getpid()))
if __name__=='__main__':
print('⽗进程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('⼦进程将要执⾏')
p.start()
p.join()
print('⼦进程已结束')
其中join()⽅法可以等待⼦进程结束后再继续往下运⾏,通常⽤于进程间的同步。
第二种:Process⼦类
from multiprocessing import Process
import time
import os
#继承Process类
class Process_Class(Process):
#因为Process类本身也有__init__⽅法,这个⼦类相当于重写了这个⽅法,
#但这样就会带来⼀个问题,我们并没有完全的初始化⼀个Process类,所以就不能使⽤从这个类继承的⼀些⽅法和属性,
#最好的⽅法就是将继承类本身传递给Process.__init__⽅法,完成这些初始化操作
def __init__(self,interval):
Process.__init__(self)
self.interval = interval
#重写了Process类的run()⽅法
def run(self):
print("⼦进程(%s) 开始执⾏,⽗进程为(%s)"%(os.getpid(),os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_stop = time.time()
print("(%s)执⾏结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))
if __name__=="__main__":
t_start = time.time()
print("当前程序进程(%s)"%os.getpid())
p1 = Process_Class(2)
#对⼀个不包含target属性的Process类执⾏start()⽅法,就会运⾏这个类中的run()⽅法,所以这⾥会执⾏p1.run()
p1.start()
p1.join()
t_stop = time.time()
print("(%s)执⾏结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))
第三种:进程池Pool
from multiprocessing import Pool
import os,time,random
def worker(msg):
t_start = time.time()
print("%s开始执⾏,进程号为%d"%(msg,os.getpid()))
#random.random()随机⽣成0~1之间的浮点数
time.sleep(random.random()*2)
t_stop = time.time()
print(msg,"执⾏完毕,耗时%0.2f"%(t_stop-t_start))
po=Pool(3) #定义⼀个进程池,最⼤进程数3
for i in range(0,10):
#Pool.apply_async(要调⽤的⽬标,(传递给⽬标的参数元祖,))
#每次循环将会⽤空闲出来的⼦进程去调⽤⽬标
po.apply_async(worker,(i,))
print("----start----")
po.close() #关闭进程池,关闭后po不再接收新的请求
po.join() #等待po中所有⼦进程执⾏完成,必须放在close语句之后
print("-----end-----")
multiprocessing.Pool常⽤函数解析:
apply_async(func[, args[, kwds]]) :使⽤⾮阻塞⽅式调⽤func(并⾏执⾏,堵塞⽅式必须等待上⼀个进程退出才能执⾏下⼀个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;apply(func[, args[, kwds]]):使⽤阻塞⽅式调⽤funcclose():关闭Pool,使其不再接受新的任务;terminate():不管任务是否完成,⽴即终⽌;join():主进程阻塞,等待⼦进程的退出, 必须在close或terminate之后使⽤;