Python编程中,如何使用多进程完成多任务进程有哪些注意点?
一、Python编程中,使用多进程完成多任务的方法
Python提供了multiprocessing模块,可以用于在单个计算机上创建多个进程,从而实现多任务处理。下面是一个简单的例子,展示了如何使用multiprocessing模块创建多进程来完成多任务。
代码:
import multiprocessingimport time# 跳舞任务def dance(): for i in range(5): print("跳舞中...") time.sleep(0.2)# 唱歌任务def sing(): for i in range(5): print("唱歌中...") time.sleep(0.2)if __name__ == '__main__': # 创建跳舞的子进程 # group: 表示进程组,目前只能使用None # target: 表示执行的目标任务名(函数名、方法名) # name: 进程名称, 默认是Process-1, ..... dance_process = multiprocessing.Process(target=dance, name="myprocess1") sing_process = multiprocessing.Process(target=sing) # 启动子进程执行对应的任务 dance_process.start() sing_process.start()
执行结果:
唱歌中...跳舞中...唱歌中...跳舞中...唱歌中...跳舞中...唱歌中...跳舞中...唱歌中...跳舞中...
二、进程有哪些注意点
1、进程之间不共享全局变量
代码:
import multiprocessingimport time# 定义全局变量g_list = list()# 添加数据的任务def add_data(): for i in range(5): g_list.append(i) print("add:", i) time.sleep(0.2) # 代码执行到此,说明数据添加完成 print("add_data:", g_list)def read_data(): print("read_data", g_list)if __name__ == '__main__': # 创建添加数据的子进程 add_data_process = multiprocessing.Process(target=add_data) # 创建读取数据的子进程 read_data_process = multiprocessing.Process(target=read_data) # 启动子进程执行对应的任务 add_data_process.start() # 主进程等待添加数据的子进程执行完成以后程序再继续往下执行,读取数据 add_data_process.join() read_data_process.start() print("main:", g_list) # 总结: 多进程之间不共享全局变量
执行结果:
add: 0
add: 1
add: 2
add: 3
add: 4
add_data: [0, 1, 2, 3, 4]
main: []
read_data []
创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,好比是一对双胞胎,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。
2、主进程会等待所有的子进程执行结束再结束
假如我们现在创建一个子进程,这个子进程执行完大概需要2秒钟,现在让主进程执行0.5秒钟就退出程序,查看一下执行结果,示例代码如下:
import multiprocessingimport time# 定义进程所需要执行的任务def task(): for i in range(10): print("任务执行中...") time.sleep(0.2)if __name__ == '__main__': # 创建子进程 sub_process = multiprocessing.Process(target=task) sub_process.start() # 主进程延时0.5秒钟 time.sleep(0.5) print("over") exit() # 总结:主进程会等待所有的子进程执行完成以后程序再退出
执行结果:
任务执行中...任务执行中...任务执行中...over任务执行中...任务执行中...任务执行中...任务执行中...任务执行中...任务执行中...任务执行中...
说明:通过上面代码的执行结果,我们可以得知:主进程会等待所有的子进程执行结束再结束。
假如我们就让主进程执行0.5秒钟,子进程就销毁不再执行,那怎么办呢?我们可以设置守护主进程或者在主进程退出之前让子进程销毁:
守护主进程:守护主进程就是主进程退出子进程销毁不再执行子进程销毁:子进程执行结束保证主进程正常退出的示例代码:
import multiprocessingimport time# 定义进程所需要执行的任务def task(): for i in range(10): print("任务执行中...") time.sleep(0.2)if __name__ == '__main__': # 创建子进程 sub_process = multiprocessing.Process(target=task) # 设置守护主进程,主进程退出子进程直接销毁,子进程的生命周期依赖与主进程 # sub_process.daemon = True sub_process.start() time.sleep(0.5) print("over") # 让子进程销毁 sub_process.terminate() exit() # 总结:主进程会等待所有的子进程执行完成以后程序再退出 # 如果想要主进程退出子进程销毁,可以设置守护主进程或者在主进程退出之前让子进程销毁
执行结果:
任务执行中...任务执行中...任务执行中...over
三、Python多线程的通信
进程是系统独立调度核分配系统资源(CPU、内存)的基本单位,进程之间是相互独立的,每启动一个新的进程相当于把数据进行了一次克隆,子进程里的数据修改无法影响到主进程中的数据,不同子进程之间的数据也不能共享,这是多进程在使用中与多线程最明显的区别。但是难道Python多进程中间难道就是孤立的吗?当然不是,python也提供了多种方法实现了多进程中间的通信和数据共享(可以修改一份数据)。
1、进程对列Queue
Queue在多线程中也说到过,在生成者消费者模式中使用,是线程安全的,是生产者和消费者中间的数据管道,那在python多进程中,它其实就是进程之间的数据管道,实现进程通信。
from multiprocessing import Process,Queuedef fun1(q,i): print('子进程%s 开始put数据' %i) q.put('我是%s 通过Queue通信' %i)if __name__ == '__main__': q = Queue() process_list = [] for i in range(3): p = Process(target=fun1,args=(q,i,)) #注意args里面要把q对象传给我们要执行的方法,这样子进程才能和主进程用Queue来通信 p.start() process_list.append(p) for i in process_list: p.join() print('主进程获取Queue数据') print(q.get()) print(q.get()) print(q.get()) print('结束测试')
结果:
子进程0 开始put数据子进程1 开始put数据子进程2 开始put数据主进程获取Queue数据我是0 通过Queue通信我是1 通过Queue通信我是2 通过Queue通信结束测试Process finished with exit code 0
上面的代码结果可以看到我们主进程中可以通过Queue获取子进程中put的数据,实现进程间的通信。
2、管道Pipe
管道Pipe和Queue的作用大致差不多,也是实现进程间的通信。
from multiprocessing import Process, Pipedef fun1(conn): print('子进程发送消息:') conn.send('你好主进程') print('子进程接受消息:') print(conn.recv()) conn.close()if __name__ == '__main__': conn1, conn2 = Pipe() #关键点,pipe实例化生成一个双向管 p = Process(target=fun1, args=(conn2,)) #conn2传给子进程 p.start() print('主进程接受消息:') print(conn1.recv()) print('主进程发送消息:') conn1.send("你好子进程") p.join() print('结束测试')
结果:
主进程接受消息:子进程发送消息:子进程接受消息:你好主进程主进程发送消息:你好子进程结束测试Process finished with exit code 0
上面可以看到主进程和子进程可以相互发送消息。
3、Managers
Queue和Pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。那么就要用到Managers。
from multiprocessing import Process, Managerdef fun1(dic,lis,index): dic[index] = 'a' dic['2'] = 'b' lis.append(index) #[0,1,2,3,4,0,1,2,3,4,5,6,7,8,9] #print(l)if __name__ == '__main__': with Manager() as manager: dic = manager.dict()#注意字典的声明方式,不能直接通过{}来定义 l = manager.list(range(5))#[0,1,2,3,4] process_list = [] for i in range(10): p = Process(target=fun1, args=(dic,l,i)) p.start() process_list.append(p) for res in process_list: res.join() print(dic) print(l)
结果:
{0: 'a', '2': 'b', 3: 'a', 1: 'a', 2: 'a', 4: 'a', 5: 'a', 7: 'a', 6: 'a', 8: 'a', 9: 'a'}[0, 1, 2, 3, 4, 0, 3, 1, 2, 4, 5, 7, 6, 8, 9]
可以看到主进程定义了一个字典和一个列表,在子进程中,可以添加和修改字典的内容,在列表中插入新的数据,实现进程间的数据共享,即可以共同修改同一份数据。
延伸阅读1:Python协程简介
协程,又称微线程,纤程,英文名Coroutine。协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行。
猜你喜欢LIKE
相关推荐HOT
更多>>如果有子查询SQL语句的执行顺序是怎么样的?
一、如果有子查询SQL语句的执行顺序是怎么样的1、子查询作为WHERE子句的一部分子查询作为WHERE子句的一部分时,首先会执行子查询,得到结果集后...详情>>
2023-10-20 23:42:56SQL Server 2014的集成内存OLTP(Hekaton)有什么战略意义?
一、SQL Server 2014的集成内存OLTP(Hekaton)有什么战略意义1、SQL Server本来就是in memory的,任何数据库都会用大量内存去cache磁盘数据,所...详情>>
2023-10-20 18:27:43Python编程中,如何使用多进程完成多任务进程有哪些注意点?
一、Python编程中,使用多进程完成多任务的方法Python提供了multiprocessing模块,可以用于在单个计算机上创建多个进程,从而实现多任务处理。...详情>>
2023-10-20 12:27:56一次简单的redis网络请求会有哪些CPU开销?
一、网络连接开销Redis是一个基于客户端-服务端模型的网络应用程序,通过TCP/IP协议进行通信。因此,建立和维护与Redis服务器之间的网络连接会...详情>>
2023-10-20 10:12:38热门推荐
如果有子查询SQL语句的执行顺序是怎么样的?
沸制作大型软件一般选用什么类型的数据库以保护数据安全?
热sql server2000导出CSV文件用EXCEL数据格式出错怎么处理?
热oracle user_segments表的segment_name字段以BIN$开头的是什么?
新MySQL日均10万数据永久保存实现高可用可以采用什么方案?
如何将ABAP时间戳转换为JAVA时间戳,原理是什么?
Django项目中如何配置MySQL数据库?
在mysql中既然where和having都能过滤,为什么用where的多?
CSS3有哪些特性?
SQL Server 2014的集成内存OLTP(Hekaton)有什么战略意义?
用access做一个数据库,用户登录界面,不同用户权限不同,应该怎么设置?
什么是Caché数据库?
flash手机广告动画制作公司使用哪些软件?
文件过多时ls命令为什么会卡住?