千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > Python编程中,如何使用多进程完成多任务进程有哪些注意点?

Python编程中,如何使用多进程完成多任务进程有哪些注意点?

来源:千锋教育
发布人:xqq
时间: 2023-10-13 06:53:34 1697151214

一、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(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT