Python一直是一门对初学者很是友好的语言,在数据分析、Web 开发、网络安全、网络爬虫等方面应用普遍。近年来,人工智能的兴起使得 Python 更加火爆了。python
咱们在处理大量数据或者须要快速爬取多种网络资源的时候,咱们没法避免使用到进程。Cpython 解释器中多线程涉及到 GIL 问题,咱们这里暂不作考虑。linux
Python 实现多进程的方式有多种,咱们下面一一来学习一下吧。windows
Linux/Unix系统提供了一个很是特殊的函数fork()
.该函数在调用以后,调用它的进程会被复制一份,包括当前的RAM和接下来要执行的代码。
关于fork的具体内容能够阅读更多的文章:
http://blog.csdn.net/jason314...
http://blog.csdn.net/cywosp/a...安全
调用的fork()
函数,它在主进程中返回的是子进程的pid;它在子进程中反馈的是0
.
那么,咱们就能够根据fork()
函数返回的值来判断是在主进程中仍是在子进程中了。
在Python中,为咱们提供了os.fork()
。网络
import os print "Process (%s) is running" % os.getpid() i = 100 pid = os.fork() if pid == 0: print "Son process (%s) is running" % os.getpid() else: print "Main process (%s) is running" % os.getpid()
上面的代码用到了几个函数,罗列以下:多线程
可是惟一遗憾的是,fork()函数只能在linuxunix系统中使用,不能在windows系统中使用。app
Python提供了跨平台的多进程支持,multiprocessing. multiprocessing模块提供了一个Process类表明一个进程。咱们能够用Process建立一个进程。async
from multiprocessing import Process import time def son_process(name): time.sleep(2) print "Process %s is running" % name if __name__ == '__main__': son_process = Process(target=son_process, args=('Son',)) print "Son process is started" son_process.start() son_process.join() print "Son process is ended - Printed by Main Process"
上面主要用到了函数
须要注意的是,在windows下,若是子进程序不是在__main__
中建立的,那么就会出错。由于windows在建立子进程的时候,会将建立它的py文件import进去。import进去机会执行,那么就会不断地建立子进程,因此会出错。
所以在windows下,须要将其包含在__main__
中。学习
上面的提到的Process主要用于建立一个进程,如何建立多个呢?Python在multiprocessing包里为咱们提供了Pool类。
咱们可使用Pool.apply_async(func, args)
函数来建立子进程。
代码:
from multiprocessing import Pool import time def son_process(name): time.sleep(5) print "Process %s is running\n" % name pool = Pool(4) print "Son process is started" for x in range(0, 10): pool.apply_async(son_process, args=('son_%d'%x,)) pool.close() print "Mark" pool.join() print "Son process is ended - Printed by Main Process"
Wait for the worker processes to exit. One must call close() or terminate() before using join().即主进程会在.join()处等待worker进程们结束后再执行。
apply()
和apply_async()
的区别就是前者是阻塞式的,后者是非阻塞式的。
阻塞式意思就是须要等待子进程完成后才能执行主线程后续的内容。
非阻塞意思就是无需等待子进程,二者是同步进行的。
跟高阶函数map()
一致,Pool
的map()
函数是将一个可迭代对象的每个元素做用域func
。
map也分阻塞和非阻塞。
imap 与 map的区别是,map是当全部的进程都已经执行完了,并将结果返回了,那么才返回map()函数的一个list结果。
imap()则是当即返回一个iterable可迭代对象。其迭代随着进行返回的结果而逐步迭代。
imap_unordered()不保证返回的结果顺序与进程添加的顺序一致。
阻塞式函数:
Pool.apply()直接返回结果
Pool.map() 直接返回一个list
非阻塞式函数
Pool.apply_async()和Pool.map_async() 返回一个AsyncResult对象。
AsyncResult对象具备:get()
函数能够获取结果。
imap() imap_unordered()则是返回可迭代函数。
multiprocess.cpu_count()
能够返回本计算机cpu的数量。咱们在新建一个进程池的时候,若是不填写任何参数,那么进程池的容量默认就是cpu的数量。