内容简介:实战(Python3环境)运行结果:multiprocessing模块是跨平台版本的多进程模块。它提供了一个
前情:这里只是单纯介绍 Python 中的多进程的程序开发,详细的内容还需要看操作系统知识。 复制代码
fork()
-
Python 的 os 模块封装了常见的系统调用,其中就包括 fork() ,可以在 Python 程序中轻松创建子进程,实现多进程。
-
Unix/Linux 操作系统(比如常见的 Mac 咯)提供了一个 fork() 系统调用,它被调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后分别在父进程和子进程内返回。
-
子进程永远返回0,而父进程返回子进程的 ID,因为一个父进程可以 fork 出很多子进程,所以父进程要记下每个子进程的 ID,而子进程只需要调用 getppid() 就可以拿到父进程的 ID。
实战(Python3环境)
import os print("正在运行的进程是 %s ..." % os.getpid()) pid = os.fork() # 如果是子进程返回0,而父进程返回子进程的ID,有了fork调用,一个进程在接到新任务时就可以复制出一个子进程来处理新任务,常见的Apache服务器就是由父进程监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。 print("\rpid 是 %s" %pid) if pid == 0: print("子进程是 %s 和父进程是 %s." % (os.getpid(), os.getppid())) else: print("在父进程 %s 中创建了子进程 %s." % (os.getpid(), pid)) 复制代码
运行结果:
正在运行的进程是 42322 ... pid 是 46501 在父进程 42322 中创建了子进程 46501. pid 是 0 子进程是 46501 和父进程是 42322. 复制代码
multiprocessing
multiprocessing模块是跨平台版本的多进程模块。它提供了一个 Process 类来代表一个进程对象。所以不管在 Unix/Linux 操作系统,还是 Windows 操作系统,都可以用 Python 编写多进程的程序。
实战
from multiprocessing import Process import os # 子进程要执行的代码 def my_proc(name): print("运行子进程 %s." % (os.getpid())) # 相当于程序执行入口 if __name__=='__main__': print("父进程 %s." %os.getpid()) p = Process(target=my_proc, args=('test',)) # 传入需要执行的函数和函数需要的参数,用start()启动,这种方式比fork()更简单 print("子进程将要开始.") p.start() p.join() # join() 可以等待子进程结束后继续往下执行,通常用于进程间同步 print("子进程结束.") 复制代码
运行结果:
父进程 42322. 子进程将要开始. 运行子进程 46580. 子进程结束. 复制代码
进程池 Pool
如果要启动大量的子进程,可以用 进程池 创建大量的子进程
实战
from multiprocessing import Pool import os, time, random def task(name): print("运行任务 %s (%s)" %(name, os.getpid())) start = time.time() time.sleep(random.random() * 3) end = time.time() print("任务 %s 耗时 %.2f 秒" %(name, (end-start))) if __name__ == "__main__": print("父进程 %s" %(os.getpid())) p = Pool(6) for i in range(10): p.apply_async(task, args=(i,)) p.close() print("等待所有子进程完毕") p.join() # 对 Pool 对象调用 join() 方法会等待所有子进程执行完毕,调用 join() 之前必须先调用 close() ,调用 close() 之后就不能继续添加新的 Process 了 print("所有子进程执行完毕") 复制代码
运行结果:
父进程 42322 运行任务 2 (43382) 运行任务 1 (43381) 运行任务 3 (43383) 运行任务 0 (43380) 运行任务 4 (43384) 运行任务 5 (43385) 任务 4 耗时 0.05 秒 运行任务 6 (43384) 等待所有子进程完毕 任务 5 耗时 0.26 秒 运行任务 7 (43385) 任务 1 耗时 0.57 秒 运行任务 8 (43381) 任务 7 耗时 0.96 秒 运行任务 9 (43385) 任务 8 耗时 1.03 秒 任务 3 耗时 2.00 秒 任务 0 耗时 2.07 秒 任务 6 耗时 2.26 秒 任务 2 耗时 2.70 秒 任务 9 耗时 2.61 秒 所有子进程执行完毕 复制代码
任务 2,1,3,0,4,5是立刻执行的,而其他任务要等待前面某个任务完成后才执行,这是因为 Pool 的大小设置为6,因此,最多同时执行6个进程,Pool 的默认大小是 CPU 的核数 。
子进程
很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。 subprocess 模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。
进程间通信
Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python 的 multiprocessing 模块包装了底层的机制,提供了 Queue 、 Pipes 等多种方式来交换数据。
实战
from multiprocessing import Process, Queue import os, time, random # 往 queue 里写内容 def write(q): print("写内容的进程: %s" %os.getpid()) for v in 'ABC': print("把 %s 写进队列..." %v) q.put(v) time.sleep(random.random()) # 从 queue 里读内容 def read(q): print("读内容的进程: %s" %os.getpid()) while True: v = q.get(True) print("从队列中读 %s." %v) if __name__=="__main__": q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) pw.start() pr.start() pw.join() # 等待 pw 结束: pr.terminate() # pr 进程里是死循环,只能强行终止 复制代码
运行结果:
写内容的进程: 46049 读内容的进程: 46050 把 A 写进队列... 从队列中读 A. 把 B 写进队列... 从队列中读 B. 把 C 写进队列... 从队列中读 C. 复制代码
本文参考(不分先后顺序):
廖雪峰的官方网站: www.liaoxuefeng.com/wiki/101695…
希望看客老爷打赏些喝茶钱
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web 2.0 Heroes
Bradley L. Jones / Wiley / 2008-04-14 / USD 24.99
Web 2.0 may be an elusive concept, but one thing is certain: using the Web as merely a means of retrieving and displaying information is history. Today?s Web is immediate, interactive, innovative. It ......一起来看看 《Web 2.0 Heroes》 这本书的介绍吧!