1. 多进程多体验
from time import sleep
from multiprocessing import Process
import os
def son(name):
while True:
print("son -- %s"%(name))
sleep(1)
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
p = Process(target=son,args=('jeck',) ) # target 表示传入任务(方法)
p.start() # agrs 表示传入一个元组,元组如果只传入一个参数,就必须后面加 ","
while True:
print("parent")
sleep(1)
如果没有加入子进程,则Python 默认是“单进程”,而且是顺序执行
2. 进程 id
from multiprocessing import Process
import os
def son(name):
while True:
print("son -- %s (%d)"%(name,os.getpid())) # os
sleep(1)
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
# os.getpid() 可以拿到当前进程的id
# os.getppid() : 拿到当前进程的父进程的 id
print("parent : ",os.getpid()) # os.getpid() 可以拿到当前进程的id ,当切换到子进程时,拿到的是子进程的 id
p = Process(target=son,args=('jeck',) ) # target 表示传入任务(方法)
p.start()
while True:
print("parent")
sleep(1)
2.2. 实验结果
3. 父子进程的执行顺序
3.1 初体验
from time import sleep
from multiprocessing import Process
import os
def son(name):
print("子进程开启")
sleep(2)
print("子进程结束")
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
print("父进程开启")
p = Process(target=son,args=('jekc',))
p.start() # 开启进程
print("父进程结束")
# 执行结果: 父进程不会等到子进程执行结束后在执行,说明父子进程之间没有执行先后顺序的要求
# 父进程开启
# 父进程结束
# 子进程开启
# 子进程结束
3.2 p.join()
from time import sleep
from multiprocessing import Process
import os
def son(name):
print("子进程开启")
sleep(2)
print("子进程结束")
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
print("父进程开启")
p = Process(target=son,args=('jekc',))
p.start() # 开启进程
p.join() # “插队” , 只有等待父进程执行结束后,子进程才结束
print("父进程结束")
# 父进程开启
# 子进程开启
# 子进程结束
# 父进程结束
3.3 多进程中全局变量是不能共享数的
from time import sleep
from multiprocessing import Process
import os
num = 10
def son(name):
print("子进程开启")
global num #声明该变量是引用全局变量
num = 11
print("子进程结束 -- %d "%num)
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
print("父进程开启")
p = Process(target=son,args=('jekc',))
p.start()
p.join()
# 在多进程中(父子进程,兄弟进程),全局变量不能共享
# 因为:每个线程有其独立的代码段,数据栈,和程序计数器,所以在子进程中引用全局变量实际上只是拷贝其数据
# 两个 num 是完全不同的变量
print("父进程结束 %d -- "%(num))
# 父进程开启
# 子进程开启
# 子进程结束 -- 11
# 父进程结束 -- 10
4. 进程池
Pool( num )
- 表示操作进程池的 cpu 核数,默认是cpu的总核数
- 若 num>cpu核数:则Pool()里面的核数为 cpu 核数
- 若 num <= cpu 核数,则用num 个核操作进程池
- 若num=2,则进程池会同时开启2个进程,必须等待这两个进程中的一个执行完结束后才开始执行新的进程’
4.1多进程列子
# -*- coding:utf-8 -*-
from time import sleep
from multiprocessing import Process
from multiprocessing import Pool
import os
import time
import random
def son(name):
print("子进程开始:%s (%d)-- "%(name,os.getpid()))
start = time.time()
sleep(random.choice([1,2,3]))
end = time.time()
print("子进程结束:%s (%d) 耗时: %d-- "%(name,os.getpid(),end-start))
if __name__=='__main__': # 表示一个父进程,在一个进程内部创建进程,表示子进程
print("父进程开启")
# 进程池,可以创建多个进程,表示同时执行的进程的数量
pp = Pool(2) # Pool(2) : 表示使用两个核 ,默认会根据电脑cpu 是几核,传入默认参数,
for i in range(5): # 传入 Pool(2) : 表示一开始会使用两个核,则一开始“开始两个子进程”
pp.apply_async(son,args=(i,)) # 表示往进程池中放入进程
pp.close() # 关闭进程池后就不能往进程池中放入进程
pp.join() # 表示等进程池中所有的进程执行完毕后在执行父进程
print("父进程结束 -- ")
4.2多进程执行“复制操作”
没有多任务的情况
fpath = r'D:\file\fpath'
topath = r'D:\file\topath'
def copy_file(rpath,wpath):
start = time.time()
fr = open(rpath, 'rb')
fw = open(wpath, 'wb')
fw.write(fr.read()) # 将读取的二进制复制过去
fr.close()
fw.close()
end = time.time()
return end-start
def test01():
start = time.time()
for file in os.listdir(fpath):
copy_file(os.path.join(fpath,file),os.path.join(topath,file))
end = time.time()
print('cost time : %.2f' % (end-start))
多进程的情况
父进程 和 子进程没有异步执行的原因是 pp.join() :等待进程池中的任务执行完后再结束父进程
def test02():
# 多进程的方式拷贝文件
pp = Pool(4)
for file in os.listdir(fpath):
# 往进程池里面方进程
pp.apply_async(copy_file,args=(os.path.join(fpath, file), os.path.join(topath, file)))
pp.close() # 不能放进程了
pp.join() # 表示会等待子进程的任务执行结束后父进程再结束
# 如果小任务则不适合用多进程执行,因为申请进程会消耗大量的资源
def main():
test02()
5.
进程的封装**
PublicUtils.py
# 封装进程
class MyProcess(Process):
def __init__(self,name):
Process.__init__(self)
# super.__init__() # 效果一样
self.name = name
def run(self):
print('子进程 %s %s' %(self.name,os.getpid()),' 开始')
time.sleep(random.choice([1,2,3])) # 暂停
print('子进程 %s %s' %(self.name,os.getpid()),' 结束')
---------------------------
Main.py
def main():
p = MyProcess('son')
p.start() # 调用 start()方法,底层实际上调用 run()方法
6. 多进程直接通讯
# -*- coding:utf-8 -*-
from multiprocessing import Process,Queue # Quque 是在mutiprocessing 里面的
import os, time, random
def write(q):
print("Process write : %s"%(os.getpid()))
for v in ['a','b','c','d']:
q.put(v) # 将数据进队
time.sleep(1)
def read(q):
print("Process read: %s "%(os.getpid()))
while True:
v = q.get(True) # 要等里面 put 了新的数据才会从里面拿 , 所以参数是特殊的 get(True)
print("get %s from Queue "%(v))
if __name__=='__main__':
q = Queue() # Queue()是特殊的变量,位于 multiprocess 包里面,专门用于处理进程间的通讯,如果是普通的全局变量是不能进行通讯的
pw = Process(target=write,args=(q,))
pr = Process(target=read,args=(q,))
pw.start()
pr.start()
pw.join() # 等待pw 结束,才结束主线程
pr.terminate() # pr 是死循环,无法自行终止,所以强制终止