(1)进程的创建
编写完毕的代码,在没有运⾏的时候,称之为程序
正在运⾏着的代码,就成为进程
注意: 进程,除了包含代码以外,还有需要运⾏的环境等,所以和程序是有区别的
(2)进程的五状态模型
(3)用fock创建子进程
运行代码如下:
import os
print("当前进程的pid:",os.getpid())
print("当前进程的父进程:",os.getppid())
p = os.fork()
if p == 0:
print("子进程返回的信息")
else:
print("创建子进程%s,父进程是%d" %(p,os.getppid()))
运行结果如下所示:
使用fock方法的注意事项
1.执⾏到os.fork()时,操作系统会创建⼀个新的进程复制⽗进程的所有信息到⼦进程中
2.普通的函数调⽤,调⽤⼀次,返回⼀次,但是fork()调⽤⼀次,返回两次
3.⽗进程和⼦进程都会从fork()函数中得到⼀个返回值,⼦进程返回是0,⽽⽗进程中返回⼦进程的 id号
注意:多进程中,每个进程中所有数据(包括全局变量)都各有拥有⼀份,互 不影响
multiprocessing模块
Windows没有fork调⽤,由于Python是跨平台的, multiprocessing模块就是跨平台版本的多进程模块。multiprocessing模块提供了⼀个Process类来代表⼀个进程对象。
Process([group [, target [, name [, args [, kwargs]]]]])
target:表示这个进程实例所调⽤对象;
args:表示调⽤对象的位置参数元组;
kwargs:表示调⽤对象的关键字参数字典;
name:为当前进程实例的别名;
group:⼤多数情况下⽤不到;
Process类常⽤属性: name:当前进程实例别名,默认Process-N,N为从1开始计数; pid:当前进程实例的PID值;
多进程编程方法一:实例化对象
运行代码如下:
from multiprocessing import Process
import time
def task1():
print("正在听音乐")
time.sleep(1)
def task2():
print("正在编程......")
time.sleep(0.5)
def use_multi():
processes = []
for i in range(2):
p = Process(target=task1)
#让子进程执行任务
p.start()
processes.append(p)
for i in range(5):
p = Process(target=task2)
p.start()
processes.append(p)
[process.join() for process in processes]
if __name__ == '__main__':
start_time = time.time()
use_multi()
end_time = time.time()
print(end_time-start_time)
运行结果如下所示:
多进程编程方法2: 创建子类
利用重写run方法
运行代码如下:
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,music_name):
super(MyProcess,self).__init__()
self.music_name = music_name
def run(self):
print("听音乐%s" %(self.music_name))
time.sleep(1)
if __name__ == '__main__':
for i in range(10):
p =MyProcess("音乐%d" %(i))
p.start()
运行结果如下所示:
多进程编程方法三:利用进程池
为什么需要进程池Pool?
当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
进程池Pool其他实现方式
运行代码如下:
import multiprocessing
def job(id):
print("start %d...." %(id))
print("end %d...." %(id))
#创建进程池对象
pool = multiprocessing.Pool(processes = 4)
#给进程池分配任务
for i in range(10):
pool.apply_async(job,args=(i+1,))
pool.close()
#等待所有的子进程执行结束,关闭进程池对象;
pool.join()
print("所有任务执行结束.....")
运行结果如下:
课上练习:用多进程判断是否为素数
运行代码如下:
from multiprocessing import Process
def is_prime(num):
if num == 1:
return False
for i in range(2,num):
if num % i == 0:
return False
else:
return True
def task(num):
if is_prime(num):
print("%d是素数" %(num))
def use_mutli():
ps = []
for num in range(1,10000):
p = Process(target=task,args=(num,))
p.start()
ps.append(p)
[p.join() for p in ps]
def no_mutli():
for num in range(1,10000):
task(num)
def use_pool():
from multiprocessing import Pool
from multiprocessing import cpu_count
p = Pool(cpu_count())
p.map(task,list(range(1,10000)))
p.close()
p.join()
import time
if __name__ == '__main__':
start_time = time.time()
#no_mutli() #0.5684056282043457
#use_mutli()
end_time = time.time() #7.152557373046875e-07
use_pool()
print(end_time-start_time)
运行结果如下:
进程间通信
消息队列
可以使⽤multiprocessing模块的Queue实现多进程之间的数据传递,Queue 本身是⼀个消息列队程序。
Queue.qsize(): 返回当前队列包含的消息数量;
Queue.empty(): 如果队列为空,返回True,反之False ;
Queue.full(): 如果队列满了,返回True,反之False;
Queue.get([block[, timeout]]): 获取队列中的⼀条消息,然后将其从列队中移除,block默认值为True;
Queue.get_nowait(): 相当Queue.get(False);
Queue.put(item,[block[, timeout]]): 将item消息写⼊队列,block默认值 为True;
Queue.put_nowait(item): 相当Queue.put(item, False)
进程间通信代码如下:
from multiprocessing import Process
import multiprocessing
import time
class producer(multiprocessing.Process):
def __init__(self,queue):
super(producer,self).__init__()
self.queue = queue
def run(self):
for i in range(10):
self.queue.put(i)
time.sleep(0.1)
print("传递消息,内容为%s" %(i))
class Consumer(multiprocessing.Process):
def __init__(self,queue):
super(Consumer,self).__init__()
self.queue = queue
def run(self):
while True:
time.sleep(0.1)
recvData = self.queue.get()
print("接受到另一进程传递的数据:%s" %(recvData))
if __name__ == '__main__':
q = multiprocessing.Queue()
p1 = producer(q)
c1 = Consumer(q)
p1.start()
c1.start()
p1.join()
c1.join()
运行结果如下: