Day10-2【Python 进程和线程】多进程编程:让Python程序“分身术”

Python多进程编程全解析

大家好,今天我们来聊聊Python中的多进程(multiprocessing)编程。你有没有想过,为什么我们可以同时在电脑上做很多事情,比如打开一个浏览器、听音乐、同时还有Word在忙着帮你排版?这就得归功于“多任务”的概念,但你知道吗,背后可有大大的“操作系统魔法”在支撑着呢!

 

28308612ea6f8c9282ac43eae1d0f33c.jpeg

 

接下来,我们将通过幽默轻松的方式,带你走进多进程的世界。首先,了解操作系统里的神奇魔法,再看看如何用Python来实现它。

一、操作系统的多进程魔法:fork()调用

让我们先从操作系统的“父子关系”谈起——是的,你没听错,进程间居然也有“父子”之分!

在Unix/Linux系统中,有一个特别的系统调用叫做fork(),它的工作原理也相当有趣:一个进程调用fork(),会得到两个返回值,分别是“父进程”和“子进程”。父进程返回的是子进程的ID,而子进程永远返回0。为什么这样设计呢?因为父进程可能要管多个子进程,它得记录下每个子进程的ID,而子进程只要知道自己的父亲是谁就好啦。

pythonimport os
print('Process (%s) start...' % os.getpid())pid = os.fork()if pid == 0:    print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))else:    print('I (%s) just created a child process (%s).' % (os.getpid(), pid))

 

运行结果大概是这样的:

scssProcess (876) start...I (876) just created a child process (877).I am child process (877) and my parent is 876.

 

但是注意!Windows没有这个fork()功能,所以如果你在Windows系统上运行上面的代码,它将无法工作。所以,想在本地实现这个神奇的操作系统魔法,推荐大家用Mac OS X,毕竟它也是基于Unix的嘛!

 

二、Python的跨平台解决方案:multiprocessing

好消息是,Python不会让你因为Windows没有fork()而痛苦不堪。Python为我们提供了一个跨平台的多进程支持模块——multiprocessing

这个模块提供了一个Process类,帮助我们更轻松地启动子进程,并且它在不同操作系统上都能正常工作。用起来比fork()方便多了,因为只需要指定一个函数和参数,Python就会帮你搞定启动进程的事。

pythonfrom multiprocessing import Processimport os
def run_proc(name):    print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__ == '__main__':    print('Parent process %s.' % os.getpid())    p = Process(target=run_proc, args=('test',))    print('Child process will start.')    p.start()    p.join()    print('Child process end.')

 

运行结果:

arduinoParent process 928.Child process will start.Run child process test (929)...Process end.

 

这段代码中,p.start()启动子进程,p.join()让父进程等待子进程结束后再继续。你看,多进程操作简直轻松得像打开一个新的网页一样!

 

 

三、想要更多子进程?用进程池(Pool)

如果你想要启动多个进程来处理任务怎么办?简单,用进程池Pool)来批量创建进程。就像你去超市购物,直接拿个购物车,一次性装满所有东西。​​​​​​​

pythonfrom multiprocessing import Poolimport os, time, random
def long_time_task(name):    print('Run task %s (%s)...' % (name, os.getpid()))    start = time.time()    time.sleep(random.random() * 3)    end = time.time()    print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__ == '__main__':    print('Parent process %s.' % os.getpid())    p = Pool(4)    for i in range(5):        p.apply_async(long_time_task, args=(i,))    print('Waiting for all subprocesses done...')    p.close()    p.join()    print('All subprocesses done.')

 

在这个例子中,我们创建了一个包含4个进程的进程池,并将5个任务分配给这些进程来执行。注意,最多只能同时执行4个任务,因为进程池的大小是4。你可以修改池的大小,看看结果会有什么不同。

运行时,子进程们会“摇摇晃晃”地开始工作,每个任务执行的时间不一致,最后等待所有任务完成。到了最后,父进程才宣布“所有任务完成!”

 

 

四、进程间通信:Queue

进程之间有时候需要“交换信息”,比如,一个进程生成了数据,另一个进程要用这个数据。这时候就需要进程间通信。Python的multiprocessing模块提供了几种方式来让进程互相传递数据,Queue就是最常用的一种。

假设有两个进程,一个负责写数据,另一个负责读数据。我们可以这样写:​​​​​​​

pythonfrom multiprocessing import Process, Queueimport 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__':    q = Queue()    pw = Process(target=write, args=(q,))    pr = Process(target=read, args=(q,))    pw.start()    pr.start()    pw.join()    pr.terminate()

 

运行结果:​​​​​​​

vbnetProcess to write: 50563Put A to queue...Process to read: 50564Get A from queue.Put B to queue...Get B from queue.Put C to queue...Get C from queue.

 

通过Queue,进程可以安全地交换数据。这里,父进程创建了一个队列,然后启动两个子进程:一个负责写入数据,另一个负责读取数据。通过q.put()q.get(),进程间就完成了信息的传递。

 

*小结

通过multiprocessing模块,Python让我们可以轻松创建多进程程序,而且它还跨平台支持——不论你是Windows、Mac还是Linux,都能轻松搞定!只要掌握了进程池(Pool)、进程通信(Queue)等技术,你就能把你的程序做得像蜘蛛网一样高效、并行运行。


上机题目:让我们动手实践!

题目1:进程池中的并行任务

编写一个Python程序,使用Pool创建10个进程,并让每个进程执行一个任务,任务是计算从1到1000的所有整数之和。

题目2:进程间通信

使用multiprocessing.Queue实现父进程生成一组随机整数,子进程读取并计算这些整数的平均值,然后返回给父进程。


祝你在多进程的世界里畅游!

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值