进程
进程的概念
- 通俗的讲,进程就是运行中的程序加上占用的资源称为进程,程序只有一个,但是进程可以有多个,它是操作系统分配资源的基本单位。进程的状态分为就绪、运行、等待(堵塞)、死亡。
- 就绪态:运行的条件已经过去,正在等待cpu执行
- 执行态: cpu正在执行其功能
- 等待态:等待某些条件,例如休眠状态
进程的实现
from multiprocessing import Process
import time
def test1():
while True:
print(----TEST1----)
time.sleep()
def test2():
while True:
print(----TEST2----)
time.sleep()
def main():
p1 = Process(target=test1)
p2 = Process(target=test2)
p1.start()
p2.start()
if __name__ == "__main__":
main()
注意:Linux中查看进程的方式是:ps -aux
杀进程的方式是:kill 进程id
进程和线程的区别
- 进程:能完成多任务,相当于开多个QQ;线程:能完成多任务,相当于QQ开多个聊天窗口。先有进程,后有线程,进程是资源分配的单位,线程是操作系统系统调度的单位
- 以工厂流水线为例,进程相当于控制台的资源,线程相当于组装零件的工人。进程之间不共享全局变量。
- 优缺点比较:线程执行开销小,但不利于资源的管理和保护,进程反之,线程是比进程轻量级的多任务。进程耗费资源,考虑到硬件的支持,进程不见得越多越好,主进程子进程的代码所占的内存是唯一的,但是数据是多份的,代码是在修改后才,子进程才拷贝,传说中的写时拷贝。
通过队列完成进程之间的通信
多个线程不能独立执行,必须依存在进程中
from multprocessing import Queue
# 创建队列及队列个数
q = Queue(3)
# 向队列里面放数据,数据类型任意
# 如果队列满了会堵塞,在那里
q.put("111")
q.put(222)
q.put([11,22,33])
# 从队列里取数据
q.get()
# 不等待的去取数据,队列为空时抛出异常
q.get_nowait()
# 判断是否为满
q.full()
# 判断是否为空
q.empty()
利用队列来实现变量共享通信
import multiprocessing
def download_from_web(q):
"""下载数据"""
# 模拟网上下载数据
data = [11,22,33,44]
# 向队列中写入数据
for temp in data:
q.put(temp)
print(----下载完成----)
def data_analysis(q):
"""分析数据"""
waiting_data = list()
while True:
data = q.get()
waiting_data.append(data)
if q.empty():
break
print(waiting_data)
def main():
# 创建一个队列,默认内存最大
q = multiprocessing.Queue()
# 创建多个进程,将队列的引用当作实参传到里面,注意是参数是元组格式
t1 = multiprocessing.Processing(target=download_from_web,args=(q,))
t2 = multiprocessing.Processing(target=data_analysis)
t1.start()
t2.start()
if __name__ == "__main__":
main()
进程池Pool
当需要创建子进程数目不多时,可以直接利用Processing动态的创建多个进程,但是如果是上百或者上千的手动创建进程的工作量巨大,此时可以利用Pool方法,初始化Pool时,可以指定最大的进程数,如果为空则计算机默认计算
from multiprocessing import Pool
import os,time,random
def worker(msg):
# 获取进程开始时间
t_start = time.time()
print("%s开始执行,进程号为%d" % (msg,os,getpid()))
time.sleep(random.random()*2)
# 获取进程结束时间
t_stop = time.time()
print(msg,"执行完毕,耗时%0.2f" % (t_stop-t_start))
po = Pool(3)
for i in range(0,10):
p0.apply_async(worker,(i,))
print("----start-----")
po.close()
po.join()
print("----end-----")
案例:多任务文件夹copy
import multiprocessing
import os
import Manger
def dir_copy(q,file_name,old_folder_name,new_folder_name):
old_f = open(older_folder_name + '/'+ file_name,"rb")
content = old_f.read()
old_f.close()
new_f = open(new_folder_name + '/' + file_name.'wb')
new_f.write(content)
new_f.close()
q.put(file_name)
def main():
# 获取需要拷贝的文件夹名称
old_folder_name = input("请输入要拷贝的文件名称")
try:
# 创建新的文件夹
folder_name = os.mkdir(older_folder_name + "复件")
new_folder_name = older_folder_name + "复件"
except:
pass
# 获取文件夹中的所有待拷贝的文件
file_names = os.listdir(old_folder_name)
print(file_names)
# 创建进程池
po = multiprocessing.Pool(5)
# 创建队列
queue = multiprossing.Manger.Queue()
# 向进程池中添加copy文件任务
for file_name in file_names:
po.apply_async(dir_copy,args(queue,
file_name,old_folder_name,new_folder_name))
po.close()
# po.join()
all_file_num = len(file_names)
copy_complete_num = 0
while True:
file_name = q.get()
copy_complete_num += 1
print("\r已经完成了:%.2f" %% (copy_complete_num*100/all_file_name,end="")
if copy_complete_num >= all_file_name:
break
print()
if __name__ =="__main__"
main()