mysql 第九节 多进程开发
=====day09.多进程开发==================
1.回顾:
Lock
队列分类 (先进先出,先进后出,优先级队列,双向队列)
生产者消费者 (用到队列和多线程)
2.什么是多进程?
1.概念:
一个程序运行起来后,代码+用到的资源 称之为进程,
它是操作系统分配资源的基本单元。
线程:是程序执行的最小单元,
是系统独立调度和分配CPU(独立运行)的基本单位。
进程:分配和管理资源的基本单位。一个进程包括多个线程。
多进程:同时执行的多个程序。
3.multiprocessing模块:
-- 1.Unix/Linux操作系统:(引言,引出multiprocessing)
-- Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。
-- 普通的函数调用,调用一次,返回一次,但是fork()调用一次,
-- 返回两次,因为操作系统自动把当前进程(称为父进程)复制了
-- 一份(称为子进程),然后,分别在父进程和子进程内返回。
-- 子进程永远返回0,而父进程返回子进程的ID。
-- import os
-- print('进程开始启动:', os.getpid())
-- pid = os.fork()
-- if pid == 0:
-- print('我是子进程:', os.getpid())
-- else:
-- print(pid)
-- print('我是父进程:', os.getpid())
2.Windows系统?
如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。
由于Windows没有fork调用,难道在Windows上无法用Python编写多
进程的程序?
由于Python是跨平台的,自然也应该提供一个跨平台的多进程
支持。multiprocessing模块就是跨平台版本的多进程模块。
4.初识多进程:
from multiprocessing import Process
import os
def son_pid():
print('子进程pid', os.getpid())
if __name__=='__main__':
p = Process(target=son_pid)
p.start()
p.join()
print('父进程pid', os.getpid())
5.进程的状态:
为了便于管理进程,经常依据进程在执行过程中的不同情况至少
定义三种不同的进程状态:
(1)运行(running)态:进程占有处理器正在运行。
(2)就绪(ready)态:进程运行条件已满足,等待cup执行。
(3)等待(wait)态:又称为阻塞(blocked)态或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成。
-- 在一个实际的系统里进程的状态及其转换比上面叙述的复杂一些,
-- 如,引入新建态(new)和死亡/终止态(exit )。
6. Process语法结构如下:
1. Process(target=,args=(,))
target:如果传递了函数的引用,可以任务这个子进程就执行这里的代码
args:给target指定的函数传递的参数,以元组的方式传递
2.Process创建的实例对象的常用方法:
start():启动子进程实例(创建子进程)
join([timeout]):是否等待子进程执行结束,或等待多少秒。
is_alive():判断进程子进程是否还在活着。
terminate():不管任务是否完成,立即终止子进程。
3.Process创建的实例对象的常用属性:
name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
pid:当前进程的pid(进程号)
7. 给子进程指定的函数传递参数:
from multiprocessing import Process
import os+
from time import sleep
def son_process(name, age, **kwargs):
for i in range(10):
print('子进程运行中,name= %s,age=%d ,pid=%d...' % (name, age, os.getpid()))
print(kwargs)
sleep(0.2)
if __name__=='__main__':
p = Process(target=son_process, args=('test',18), kwargs={"m":20})
p.start()
sleep(1) # 1秒中之后,立即结束子进程
p.terminate()
===========================
===========================
8. 进程间不共享全局变量:(反例)
from multiprocessing import Process
from threading import Thread
nums = [11, 22]
def work1():
print('work1, 加入之前nums为:', nums)
for i in range(3):
nums.append(i)
# time.sleep(1)
print("在work1中,nums为", nums)
def work2():
print("在work2中,nums为:", nums)
if __name__ == '__main__':
p1 = Process(target=work1)
p2 = Process(target=work2)
p1.start()
p2.start()
p1.join()
p2.join()
# t1 = Thread(target=work1)
# t2 = Thread(target=work2)
#
# t1.start()
# t2.start()
# t1.join()
# t2.join()
9.使用进程池:
-- 如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,
-- 此时就可以用到multiprocessing模块提供的Pool方法。
from multiprocessing import Pool
import os
import time
def task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
time.sleep(1)
if __name__ == '__main__':
print('父进程pid为:', os.getpid())
p = Pool(4)
for i in range(10):
p.apply_async(task, args=(i,))
# close():关闭Pool,使其不再接受新的任务;
p.close()
# join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
p.join()
print('所有任务都结束了')
10.进程间通信:
Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。
Python的multiprocessing模块包装了底层的机制,提供了Queue、管道Pipes
共享内存、 套接字socket、 信号。
from multiprocessing import Process, Queue, Pool
import 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()
===========管道的应用例子,创建一个管道,两个口都能收发
import multiprocessing
import os
def func(conn): #conn管道类型
conn.send(["a","b","c","d","e"]) #发送的数据
print("子进程",os.getpid(),conn.recv()) #收到的数据
conn.close() #关闭
if __name__=="__main__":
conn_a,conn_b=multiprocessing.Pipe() #创建一个管道,两个口
#print(id(conn_a),id(conn_b))
#print(type(conn_a), type(conn_b)) #multiprocessing.connection.PipeConnection类型
p=multiprocessing.Process(target=func,args=(conn_a,))
p.start()
conn_b.send([1,2,3,4,5,6,7])
print("主进程:",os.getpid(),conn_b.recv())
p.join()
===========================================
11.总结:
进程与线程区别
进程间通信
进程池